home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGambit 2.0 / sources1 / Runtime (.c & .h) / os_mac.c < prev    next >
Encoding:
Text File  |  1993-02-05  |  99.4 KB  |  2,557 lines  |  [TEXT/KAHL]

  1. ght - r.left ) >> 1 ) + SBarWidth + 1;
  2.   r.top = r.bottom - SBarWidth + 1;
  3.   SetPort( port );
  4.   InvalRect( &r );
  5. }
  6. static void inval_msgrect( short w )
  7. { if ( showPosnP ) wind_table[w].needs_inval_ticks = TickCount();
  8. }
  9. static void content( short id, EventRecord *event )
  10. { WindowPtr w = wind_table[id].wptr;
  11.   eTeHandle hTE = wind_table[id].hTE;
  12.   short cntlCode;
  13.   ControlHandle theControl;
  14.   ChPos oldCaret;
  15.  
  16.   SetPort( w );
  17.   ClipRect( &w->portRect );
  18.   GlobalToLocal( &event->where );
  19.   if ((cntlCode = FindControl( event->where, w, &theControl )) == 0 )
  20.   { if (PtInRect( event->where, &(**hTE).viewRect ))
  21.     { oldCaret = (**hTE).caretChPos;
  22.       eTeClick( hTE, event->where, event->modifiers, event->when );
  23.       if ( *(long *)&oldCaret != *(long *)&(**hTE).caretChPos ) inval_msgrect( id );
  24.     }
  25.   }
  26.   else if (cntlCode == inThumb)
  27.   { cntlCode = GetCtlValue( theControl );
  28.     TrackControl( theControl, event->where, 0L );
  29.     if ( ( cntlCode = GetCtlValue( theControl ) - cntlCode ) != 0 )
  30.         if( (**theControl).contrlRect.left < (**theControl).contrlRect.top ) /* horizontal? */
  31.             eTeScroll( hTE, cntlCode, 0, TRUE );
  32.         else
  33.             eTeScroll( hTE, 0, cntlCode, TRUE );
  34.   }
  35.   else
  36.     TrackControl( theControl, event->where, (ProcPtr )-1L );
  37. }
  38. #endif
  39.  
  40. /* 10Jan93  e -- added display of caret position */
  41. #if (eTe_SHOW_POSN == 0)
  42. static void update_window( short w )
  43. { GrafPtr port = wind_table[w].wptr;
  44.   Rect r = port->portRect;
  45. #ifdef USE_eTe_debug
  46.   Str255 tStr;
  47. #endif
  48.   r.right -= (( r.right - r.left ) >> 1 ) + SBarWidth + 1;
  49.   r.top = r.bottom - SBarWidth;
  50.   SetPort( port );
  51.   ClipRect( &port->portRect );    /* added for eTe  16Apr92  e  */
  52.   BeginUpdate( port );
  53.   EraseRect( &port->portRect );
  54.   DrawControls( port );
  55.   DrawGrowIcon( port );
  56.   EraseRect( &r );
  57.   MoveTo( r.left, r.top );
  58.   LineTo( r.right, r.top );
  59. #ifdef USE_eTe_debug
  60.   NumToString( eTeTextLength( wind_table[w].hTE ), tStr);
  61.   MoveTo( r.left + 4, r.bottom - 4 );
  62.   ClipRect( &r );
  63.   DrawString( (ConstStr255Param )tStr );
  64. #endif
  65.   eTeUpdate( wind_table[w].hTE );
  66.   EndUpdate( port );
  67. }
  68. #else
  69. static void update_window( short w )
  70. { GrafPtr port = wind_table[w].wptr;
  71.   Rect r = port->portRect;
  72.   Str255 tStr;
  73.   eTeHandle hTE;
  74.   r.right -= (( r.right - r.left ) >> 1 ) + SBarWidth + 1;
  75.   r.top = r.bottom - SBarWidth;
  76.   SetPort( port );
  77.   ClipRect( &port->portRect );    /* added for eTe  16Apr92  e  */
  78.   BeginUpdate( port );
  79.   EraseRect( &port->portRect );
  80.   DrawControls( port );
  81.   DrawGrowIcon( port );
  82.   EraseRect( &r );
  83.   MoveTo( r.left, r.top );
  84.   LineTo( r.right, r.top );
  85. #ifdef USE_eTe_debug
  86.   NumToString( eTeTextLength( wind_table[w].hTE ), tStr);
  87.   MoveTo( r.left + 4, r.bottom - 4 );
  88.   ClipRect( &r );
  89.   DrawString( (ConstStr255Param )tStr );
  90. #else
  91.   if ( showPosnP )
  92.   { hTE = wind_table[w].hTE;
  93.     MoveTo( r.left + 4, r.bottom - 4 );
  94.     ClipRect( &r );
  95.     NumToString( (long )(**hTE).caretChPos.v, tStr);
  96.     DrawString( (ConstStr255Param )tStr );
  97.     DrawString( "\p:" );
  98.     NumToString( (long )(**hTE).caretChPos.h, tStr);
  99.     DrawString( (ConstStr255Param )tStr );
  100.   }
  101. #endif
  102.   eTeUpdate( wind_table[w].hTE );
  103.   EndUpdate( port );
  104. }
  105. #endif
  106.  
  107. static void grow_window( id, p )
  108. short id;
  109. Point p;
  110. { WindowPtr w = wind_table[id].wptr;
  111.   long result;
  112.   short oScroll;
  113.   Rect r, oView;
  114.   
  115.   SetPort( w );
  116.  
  117.   /* 16Sep92  e  increase min size for H scroll bar
  118.   SetRect(&r, 80, 80, screenBits.bounds.right, screenBits.bounds.bottom); */
  119.   /* 13Oct92  e  per: bernard@sigi.cs.colorado.edu
  120.   SetRect(&r, 150, 80, screenBits.bounds.right, screenBits.bounds.bottom); */
  121.   r = (**GetGrayRgn()).rgnBBox;
  122.   r.top = 80;
  123.   r.left = 150;
  124.   /*  13Oct92  e  */
  125.   result = GrowWindow( w, p, &r );
  126.   if (result == 0) return;
  127.   SizeWindow( w, LoWord(result), HiWord(result), 1);
  128.  
  129.   InvalRect(&w->portRect);
  130.   setup_view( id );
  131.   HideControl( wind_table[id].vscroll );
  132.   MoveControl( wind_table[id].vscroll, w->portRect.right - SBarWidth, w->portRect.top-1);
  133.   SizeControl( wind_table[id].vscroll, SBarWidth+1, w->portRect.bottom - w->portRect.top-(SBarWidth-2));
  134.   HideControl( wind_table[id].hscroll );
  135.   MoveControl( wind_table[id].hscroll,
  136.                   w->portRect.right-((w->portRect.right-w->portRect.left)>>1),
  137.                   w->portRect.bottom - SBarWidth);
  138.   SizeControl( wind_table[id].hscroll,
  139.                   ((w->portRect.right-w->portRect.left)>>1)-(SBarWidth-1),
  140.                   SBarWidth+1);
  141.   ShowControl( wind_table[id].hscroll );
  142.   ValidRect(&(*wind_table[id].hscroll)->contrlRect );
  143.   ShowControl( wind_table[id].vscroll );
  144.   ValidRect(&(*wind_table[id].vscroll)->contrlRect );
  145.   update_window( id );
  146.   /* dunno (sometimes appropriate, sometimes not)... eTeShowCaret( wind_table[id].hTE ); */
  147. }
  148.  
  149. static void put_input( id, ptr, len, cr, flush, freshline )
  150. short id;
  151. char *ptr;
  152. short len;
  153. short cr, flush, freshline;
  154. { if (wind_table[id].in_use)
  155.   { long len1;
  156.     register long len2 = (wind_table[id].len - wind_table[id].pos);
  157.     register char *buf, *p1, *p2;
  158.     if ((len2 < 0) || flush) len2 = 0;
  159.     len1 = ((cr)?1:0) + len2 + (long)len;
  160.     buf = NewPtr( len1 );
  161.     if (buf == NULL) { SysBeep(10); return; }
  162.     p1 = buf;
  163.     p2 = wind_table[id].buf + wind_table[id].pos;
  164.     while (len2 > 0) { *p1++ = *p2++; len2--; }
  165.     p2 = ptr;
  166.     while (len > 0) { *p1++ = *p2++; len--; }
  167.     if (cr) *p1++ = '\r';
  168.     if (wind_table[id].buf != NULL) DisposPtr( wind_table[id].buf );
  169.     wind_table[id].buf = buf;
  170.     wind_table[id].pos = 0;
  171.     wind_table[id].len = len1;
  172.     if (freshline)
  173.     { eTeHandle hTE = wind_table[id].hTE;
  174.       if ( (**hTE).caretChPos.h > 0 ) check_TEInsert( "\r", 1L, hTE, 0 );
  175.       (**hTE).writeChPos = (**hTE).caretChPos; /*  9Jul92  e  */
  176.       eTeShowCaret( hTE );
  177.     }
  178.   }
  179. }
  180.  
  181. static void interrupt()
  182. { intr_action( 0L, 0L, "SIGINT" );
  183.   put_input( interaction_id, "", 0, 0, 1, 0 );
  184. }
  185.  
  186. static short open_file( filename, for_output, txt, io )
  187. Str255 filename;
  188. short for_output;
  189. short txt;
  190. short *io;
  191. { ioParam pb;
  192.   fileParam fp;
  193.   short refnum;
  194.   short len = (unsigned char)filename[0];
  195.   short file_existed = 1;
  196.  
  197.   pb.ioNamePtr = filename;
  198.   pb.ioVRefNum = current_volume;
  199.   pb.ioVersNum = 0;
  200.   pb.ioPermssn = ((for_output) ? fsRdWrPerm : fsRdPerm);
  201.   pb.ioMisc = 0;
  202.  
  203.   if (for_output)
  204.   { asm
  205.     { lea    pb,a0
  206.       _PBCreate
  207.     }
  208.     file_existed = (pb.ioResult == dupFNErr);
  209.     if ((pb.ioResult != noErr) && !file_existed)
  210.     { *io = pb.ioResult;  return -1; }
  211.   }
  212.   
  213.   asm
  214.   { lea    pb,a0
  215.     _PBOpen
  216.   }
  217.   if (pb.ioResult != noErr)
  218.   { if (for_output)
  219.       asm
  220.       { lea    pb,a0
  221.         _PBDelete
  222.       }
  223.     *io = pb.ioResult;
  224.     return -1;
  225.   }
  226.   refnum = pb.ioRefNum;
  227.   
  228.   if (!for_output) { *io = noErr; return refnum; }
  229.  
  230.   asm
  231.   { lea    pb,a0
  232.     _PBSetEOF
  233.   }
  234.  
  235.   if (!file_existed)
  236.   { fp.ioNamePtr = filename;
  237.     fp.ioVRefNum = current_volume;
  238.     fp.ioFVersNum = 0;
  239.     fp.ioFDirIndex = 0;
  240.     asm
  241.     { lea    fp,a0
  242.       _PBGetFInfo
  243.       bmi.s  @1
  244.     }
  245.     if (txt)
  246.       fp.ioFlFndrInfo.fdType = 'TEXT';
  247.     else
  248.       fp.ioFlFndrInfo.fdType = 'gamO';
  249.     fp.ioFlFndrInfo.fdCreator = 'gamI';
  250.     asm
  251.     { lea    fp,a0
  252.       _PBSetFInfo
  253.       @1
  254.     }
  255.   }
  256.  
  257.   *io = noErr;
  258.   return refnum;
  259. }
  260.  
  261. static short close_file( refnum, io )
  262. short refnum;
  263. short *io;
  264. { *io = FSClose( refnum );
  265.   return (*io != noErr);
  266. }
  267.  
  268. static short read_file( id, line, chr )
  269. short id;
  270. long line;
  271. long chr;
  272. { TeHANDLE hTE = wind_table[id].hTE;
  273.   short refnum;
  274.   short io, io2;
  275.   long pos = 0;
  276.   short result;
  277.   Rect r;
  278.   short beep = 0;
  279.   short text = 0;
  280.   long size, count;
  281.   ChPos chPos;
  282.   Handle hData;
  283.   
  284.   if ( line > 32768 )
  285.   { te_limit_err();
  286.     return 0;
  287.   }
  288.   chPos.v = (line==0) ? 0 : line-1;
  289.   chPos.h = (line==0) ? 0 : chr;
  290.  
  291.   SelectWindow( wind_table[id].wptr );
  292.  
  293.   if (wind_table[id].dirty)
  294.     if (!discard_changes( id )) return 0;
  295.   
  296.   refnum = open_file( wind_table[id].filename, 0, 1, &io );
  297.   if (refnum == -1)
  298.   { io_err( io );
  299.     return 0;
  300.   }
  301.  
  302.   eTeSetTextPtr( hTE, (Ptr )&text, 1L );
  303.   io = GetEOF(refnum, &size);
  304.   if( io == noErr )    {
  305.     if( hData = NewHandle( size + 1 ) )
  306.     {    HLock( hData );
  307.         count = size;
  308.         io = FSRead( refnum, &count, *hData );
  309.         HUnlock( hData );
  310.         if( ( io != noErr ) || ( count != size ) )
  311.         {    DisposHandle( hData );
  312.             if ( io == noErr ) io = ioErr;
  313.             /* io_err( io ); will happen */
  314.             /* added these next lines 7Jul92  e */
  315.             mem_full = 0;
  316.               eTeSetTextPtr( hTE, (Ptr )&text, 1L );
  317.         }
  318.         else
  319.         {    ((char *)*hData)[size] = '\0';
  320.             io = eTeSetTextHandleDetabify( hTE, hData, prefTabs );
  321.             if ( io == noErr )
  322.             {   count = eTeChPosToOffset( hTE, chPos );
  323.                 if ( count > 0 )
  324.                     eTeSetSelect( hTE, count-1, count );
  325.                 else
  326.                     eTeSetSelect( hTE, count, count );
  327.                 eTeShowCaret( hTE );
  328.             }
  329.             else
  330.             {    DisposHandle( hData );
  331.                 /* io_err( io ); will happen */
  332.                 /* added these next lines 7Jul92  e */
  333.                 mem_full = 0;
  334.                   eTeSetTextPtr( hTE, (Ptr )&text, 1L );
  335.             }
  336.           }
  337.       }
  338.       else
  339.       { mem_full = 0; io = mFulErr; }     /* mem_full = 0; added  7Jul92  e */
  340.   }
  341.  
  342.   if (close_file( refnum, &io2 ) || ((io != eofErr) && (io != noErr)))
  343.   { if ((io != eofErr) && (io != noErr)) io_err( io ); else io_err( io2 );
  344.       eSmudgeWindow( id );
  345.       return 0;
  346.   }
  347.   if (io != noErr)
  348.       eSmudgeWindow( id );
  349.   else
  350.       eUnSmudgeWindow( id, hTE );
  351.   return (io == noErr);
  352. }
  353.  
  354. static void write_file( id )
  355. short id;
  356. { TeHANDLE hTE = wind_table[id].hTE;
  357.   short refnum;
  358.   short io, io2;
  359.   long count;
  360.  
  361.   refnum = open_file( wind_table[id].filename, 1, 1, &io );
  362.   if (refnum == -1)
  363.   { io_err( io );
  364.     return;
  365.   }
  366.  
  367.   count = eTeTextLength( hTE );
  368.   io = FSWrite( refnum, &count, *((**hTE).hText) );
  369.  
  370.   if (close_file( refnum, &io2 ) || (io != noErr))
  371.   { if (io != noErr) io_err( io ); else io_err( io2 );
  372.     return;
  373.   }
  374.  
  375.   eUnSmudgeWindow( id, hTE );
  376. }
  377.  
  378. short edit( name, line, chr )
  379. char *name;
  380. long line;
  381. long chr;
  382. { short id;
  383.   Str255 pname;
  384.   c_to_p( name, pname );
  385.   if (pname[0] != '\0')
  386.   { for (id=0; id<MAX_NB_WINDOWS; id++)
  387.       if (wind_table[id].in_use && wind_table[id].is_file &&
  388.           (compare_p_to_p( wind_table[id].filename, pname ) == 0)) break;
  389.   }
  390.   else
  391.     id = MAX_NB_WINDOWS;
  392.  
  393.   if (id == MAX_NB_WINDOWS) id = wind_open( name, /* 27Jan93 e -- TRUE */ FALSE, TRUE, FALSE );
  394.   if (id < 0)
  395.     wind_err();
  396.   else
  397.   { wind_table[id].is_file = 1;
  398.     p_to_p( pname, wind_table[id].filename );
  399.     supress_mem_full_dialog = 1;        /* 27Jan93  e  */
  400.     if ( read_file( id, line, chr ) )
  401.         select_and_show( wind_table[id].wptr );
  402.     else
  403.         wind_close( id );
  404.     supress_mem_full_dialog = 0;        /* 27Jan93  e  */
  405.   }
  406.   return id;
  407. }
  408.  
  409. void save_as( id, path )
  410. short id;
  411. char *path;
  412. { Str255 ppath;
  413.   short i;
  414.   c_to_p( path, ppath );
  415.   for (i=0; i<MAX_NB_WINDOWS; i++)
  416.     if (wind_table[i].in_use && wind_table[i].is_file &&
  417.         (compare_p_to_p( wind_table[i].filename, ppath ) == 0))
  418.     { already_open_err( ppath );
  419.       return;
  420.     }
  421.   p_to_p( ppath, wind_table[id].filename );
  422.   if (wind_table[id].is_file) SetWTitle( wind_table[id].wptr, ppath );
  423.   if ( id != interaction_id ) /* 28Jan93  e  */
  424.   { delWindMenuItem( id );
  425.     addWindMenuItem( id );
  426.   }
  427.   write_file( id );
  428. }
  429.  
  430. static void wind_quit()
  431. { short id;
  432.   for (id=MAX_NB_WINDOWS-1; id>=0; id--)
  433.   { if (wind_table[id].in_use && wind_table[id].is_file && wind_table[id].dirty)
  434.     { if (!discard_changes( id )) return;
  435.       wind_close( id );
  436.     }
  437.   }
  438.   abnormal_exit = 0;
  439.   /* os_quit();    29Dec92  e  */
  440.   gDoQuit = 1;    /* 29Dec92  e  */
  441. }
  442.  
  443. static void handle_close( id )
  444. short id;
  445. { if (wind_table[id].is_file)
  446.   { if ((wind_table[id].dirty) && (!discard_changes( id ))) return;
  447.     wind_close( id );
  448.   }
  449.   else if (id != interaction_id)
  450.     put_input( id, "\004", 1, 0, 1, 0 );
  451. }
  452.  
  453. static char upcase( char c )
  454. { if( c >= 'a' &&  c <= 'z' ) return c - 0x20;
  455.   else return c;
  456. }
  457. /* 08Jan93  e  -- changed to return Boolean; added test for empty find string */
  458. Boolean find_next( id )
  459. short id;
  460. { TeHANDLE hTE = wind_table[id].hTE;
  461.   char *txt = *((**hTE).hText);
  462.   long pos = eTeChPosToOffset( hTE, (**hTE).selActive ? (**hTE).selEnd : (**hTE).caretChPos );
  463.   register char *start = txt + pos - 1;
  464.   register short len = (unsigned char)find_string[0];
  465.   register char *end = txt + eTeTextLength( hTE ) - len;
  466.   register short i;
  467.   Boolean again = TRUE;
  468.   Str255 ci_string;
  469.   if ( len == 0 ) goto not_found;
  470.   if( find_ci )
  471.   { for (i=len; i>0; i--)
  472.       ci_string[i] = upcase( find_string[i] );
  473.     /* ci_string[0] = len; -- not used */
  474.   }
  475.   find_begin:
  476.   while (start < end)
  477.   { if( find_ci )
  478.     { for (i=len; i>0; i--)
  479.         if( upcase( start[i] ) != (char )ci_string[i] ) goto next_pos;
  480.     }
  481.     else
  482.     { for (i=len; i>0; i--)
  483.         if (start[i] != (char )find_string[i]) goto next_pos;
  484.     }
  485.     eTeSetSelect( hTE, (long)(start-txt+1), (long)(start-txt+1+len) );
  486.     return 1;
  487.     next_pos:
  488.     start++;
  489.   }
  490.   if( find_wrap && again ) 
  491.   { start = txt;
  492.     end = start + pos - len;
  493.     again = FALSE;
  494.     goto find_begin;
  495.   }
  496. not_found:
  497.   SysBeep(10);
  498.   return 0;
  499. }
  500.  
  501. void replace_next( id )
  502. short id;
  503. { TeHANDLE hTE = wind_table[id].hTE;
  504.   if ( ! (**hTE).selActive )
  505.     SysBeep(10);
  506.   else
  507.   { long len = (unsigned char)replace_string[0];
  508.     check_TEInsert( ((char *)replace_string)+1, len, hTE, wind_table[id].bold_input );
  509.     find_next( id );
  510.     eTeShowCaret( hTE );
  511.   }
  512. }
  513.  
  514. /* 08Jan93  e  */
  515. void replace_all( id )
  516. short id;
  517. { TeHANDLE hTE = wind_table[id].hTE;
  518.   long len = (unsigned char)replace_string[0];
  519.   
  520.   if ( (**hTE).selActive )
  521.   { long pos = eTeChPosToOffset( hTE, (**hTE).selStart );
  522.     eTeSetSelect( hTE, pos, pos );
  523.   }
  524.   while ( find_next( id ) )
  525.     check_TEInsert( ((char *)replace_string)+1, len, hTE, wind_table[id].bold_input );
  526.   eTeShowCaret( hTE );
  527. }
  528.  
  529. static long balance( id, bal, prefix )
  530. short id;
  531. short bal;
  532. short prefix;
  533. {
  534.   return balance_bwd( wind_table[id].hTE, bal, prefix );
  535.   /* bulk of code moved to os_mac_eKeys.c  11Jul92  e */
  536. }
  537.  
  538. static void balance_next( id )
  539. short id;
  540. { TeHANDLE hTE = wind_table[id].hTE;
  541.   long start = balance( id, 0, 1 );
  542.   if (start < 0)
  543.     SysBeep(10);
  544.   else
  545.     eTeSetSelect( hTE, start,
  546.                      eTeChPosToOffset( hTE, (**hTE).selActive ?
  547.                                                   (**hTE).selEnd : (**hTE).caretChPos ) );
  548. }
  549.  
  550. static void online_help()
  551. {
  552.   help_show();
  553. }
  554.  
  555. static void find_dialog( short id )
  556. { DialogPtr dp;
  557.   short i, s;
  558.   Handle h;
  559.   Rect r;
  560.   eTePutScrap();                                          /*  13Oct92  e  */
  561.   ParamText( "\pFind:", "\pReplace with:", "\p", "\p" );
  562.   dp = GetNewDialog( find_dlogID, 0L, (WindowPtr)-1L );
  563.   if (dp == NULL) return;
  564.   GetDItem( dp, 3, &i, &h, &r );
  565.   SetIText( h, find_string );
  566.   GetDItem( dp, 5, &i, &h, &r );
  567.   SetIText( h, replace_string );
  568.   GetDItem( dp, 7, &i, &h, &r);
  569.   SetCtlValue( h, find_wrap );
  570.   GetDItem( dp, 8, &i, &h, &r);
  571.   SetCtlValue( h, find_ci );
  572.   SelIText( dp, 3, 0, find_string[0] );
  573.   SetCursor( &arrow );
  574.   do
  575.   { ModalDialog( 0L, &s );
  576.     switch( s )
  577.     { case 1:
  578.         GetDItem( dp, 3, &i, &h, &r );
  579.         GetIText( h, find_string );
  580.         GetDItem( dp, 5, &i, &h, &r );
  581.         GetIText( h, replace_string );
  582.         GetDItem( dp, 7, &i, &h, &r);
  583.         find_wrap = GetCtlValue( h );
  584.         GetDItem( dp, 8, &i, &h, &r);
  585.         find_ci   = GetCtlValue( h );
  586.         break;
  587.       case 7:
  588.       case 8:
  589.         GetDItem( dp, s, &i, &h, &r );
  590.         SetCtlValue( (ControlHandle )h, GetCtlValue( (ControlHandle )h ) ^ 1 );
  591.         break;
  592.     }
  593.   } while( s != 1 && s != 2 );
  594.   DisposDialog( dp );
  595.   if( s == 1 ) find_next( id );
  596.   eTeGetScrap();                                          /*  13Oct92  e  */
  597. }
  598.  
  599. /* 25Sep92  e  added print menu items */
  600.  
  601. static void handle_pgsetup( short id )
  602.   TeHANDLE hTE = wind_table[id].hTE;
  603.   SetCursor(&qd.arrow);
  604.   PageSetupDialog( hTE );
  605. }
  606.  
  607. /* 02Oct92  e  added iPrAbort check */
  608.  
  609. static void handle_print( short id )
  610.   OSErr err;
  611.   TeHANDLE hTE = wind_table[id].hTE;
  612.   Str255 flnm;
  613.   
  614.   SetCursor(&qd.arrow);
  615.   err = noErr;
  616.   if ( ! (**hTE).hPrint )
  617.     err = PageSetupDialog( hTE );
  618.   if( ! err )
  619.   {    pathstr_to_filename( wind_table[id].filename, flnm );
  620.     err = eTePrint( hTE, true, true, flnm );
  621.     eTePrint( nil, false, false, flnm );
  622.   }
  623.   if( err && err != userCanceledErr && err != iPrAbort ) io_err( err );
  624. }
  625.  
  626. /*----------------------------------------------------------------------*/
  627.  
  628. #include "struct.h"
  629.  
  630. #define MAC_HEAP_LEN_IN_K  50 /* leave at least 50K free for Mac heap */
  631. #define MAC_STACK_LEN_IN_K 26 /* leave this much stack space for Mac calls */
  632.  
  633. long link_stack_length_in_k = -1;
  634. long link_heap_length_in_k = -1;
  635. long link_const_length_in_k = -1;
  636.  
  637. struct mem_partition
  638. { long base_heap,  extend_heap,  spare_heap;
  639.   long base_const, extend_const, spare_const;
  640.   long base_zzzzz, extend_zzzzz, spare_zzzzz;
  641.   long base_mac,   extend_mac,   spare_mac;
  642.   long spare1, spare2, spare3, spare4;
  643. } memp;
  644.  
  645. long mem_cur_heap, mem_min_heap;
  646. long mem_cur_const, mem_min_const;
  647. long mem_cur_zzzzz, mem_min_zzzzz;
  648. long mem_cur_mac, mem_min_mac;
  649.  
  650. #define DEFAULT_EXTEND_HEAP  8
  651. #define DEFAULT_EXTEND_CONST 1
  652. #define DEFAULT_EXTEND_ZZZZZ 0
  653. #define DEFAULT_EXTEND_MAC   1
  654.  
  655. static void partition_init( ofiles_len )
  656. long ofiles_len; /* total length of object files */
  657. {
  658.   struct mem_partition **memph;
  659.   long initial_free_mem;
  660.   long stack_len, system_mem_less_const_len, processor_mem_len, fixed_len;
  661.   long free_mem_before_base, free_mem_after_base;
  662.   long total_extend, extend_heap, extend_const, extend_zzzzz, extend_mac;
  663.  
  664.  
  665.   memph = (struct mem_partition **)GetResource( 'gamP', 128 );
  666.   if ((memph != NULL) && (SizeResource(memph) == sizeof(struct mem_partition)))
  667.   { memp = **memph; ReleaseResource(memph); }
  668.   else
  669.     memp.base_heap = -1; /* forces initialization later on */
  670.  
  671.  
  672.   /* initial_free_mem is the total free space at present in the Mac's heap */
  673.  
  674.   initial_free_mem = ((long)&initial_free_mem) - ((long)HeapEnd);
  675.  
  676.  
  677.   /* compute amount of free memory before partitions are allocated */
  678.  
  679.   stack_len = ((long)DEFAULT_STACK_LENGTH_IN_K)*K;
  680.  
  681.   system_mem_less_const_len =
  682.     ceiling8( sizeof(struct sstate_rec) ) +
  683.     ((long)MAX_NB_GLOBALS)*sizeof(struct global_rec) +
  684.     ((long)MAX_NB_GLOBALS)*sizeof(short) +
  685.     ((long)NB_TRAPS)*sizeof(struct trap_rec);
  686.  
  687.   processor_mem_len =
  688.     stack_len*2 +
  689.     ceiling8( ((long)MAX_NB_EVENTS)*sizeof(long) ) +
  690.     ((long)LOCAL_HEAP_LENGTH_IN_K)*K +
  691.     ceiling8( ((long)MAX_NB_STATS)*sizeof(long) ) +
  692.     ceiling8( ((long)MAX_EMUL_CODE_LENGTH_IN_K)*K ) +
  693.     ceiling8( sizeof(struct pstate_rec) );
  694.  
  695.   fixed_len = ((long)MAC_STACK_LEN_IN_K*K)+system_mem_less_const_len+processor_mem_len;
  696.  
  697.   free_mem_before_base = (initial_free_mem - fixed_len)/K;
  698.  
  699.  
  700.   /* setup partitions */
  701.  
  702.   mem_min_heap  = (long)MIN_HEAP_LENGTH_IN_K;
  703.   mem_min_const = (ofiles_len+K-1)/K + (long)ADDITIONAL_CONST_LENGTH_IN_K;
  704.   mem_min_zzzzz = 0;
  705.   mem_min_mac   = (long)MAC_HEAP_LEN_IN_K;
  706.  
  707.   if ((memp.base_heap  < mem_min_heap ) || (memp.extend_heap  < 0) ||
  708.       (memp.base_const < mem_min_const) || (memp.extend_const < 0) ||
  709.       (memp.base_zzzzz < mem_min_zzzzz) || (memp.extend_zzzzz < 0) ||
  710.       (memp.base_mac   < mem_min_mac  ) || (memp.extend_mac   < 0) ||
  711.       (memp.base_heap+memp.base_const+memp.base_zzzzz+memp.base_mac > free_mem_before_base))
  712.   {
  713.     memp.base_heap  = mem_min_heap;   memp.extend_heap  = DEFAULT_EXTEND_HEAP;
  714.     memp.base_const = mem_min_const;  memp.extend_const = DEFAULT_EXTEND_CONST;
  715.     memp.base_zzzzz = mem_min_zzzzz;  memp.extend_zzzzz = DEFAULT_EXTEND_ZZZZZ;
  716.     memp.base_mac   = mem_min_mac;    memp.extend_mac   = DEFAULT_EXTEND_MAC;
  717.   }
  718.  
  719.   free_mem_after_base = free_mem_before_base -
  720.                         (memp.base_heap+memp.base_const+memp.base_zzzzz+memp.base_mac);
  721.   if (free_mem_after_base < 0) free_mem_after_base = 0;
  722.  
  723.   total_extend = memp.extend_heap+memp.extend_const+memp.extend_zzzzz+memp.extend_mac;
  724.   if (total_extend < 1) total_extend = 1; /* to avoid divide by 0 */
  725.  
  726.   extend_heap  = (free_mem_after_base*memp.extend_heap )/total_extend;
  727.   extend_const = (free_mem_after_base*memp.extend_const)/total_extend;
  728.   extend_zzzzz = (free_mem_after_base*memp.extend_zzzzz)/total_extend;
  729.   extend_mac   = free_mem_after_base - (extend_heap+extend_const+extend_zzzzz);
  730.  
  731.   mem_cur_heap  = memp.base_heap  + extend_heap;
  732.   mem_cur_const = memp.base_const + extend_const;
  733.   mem_cur_zzzzz = memp.base_zzzzz + extend_zzzzz;
  734.   mem_cur_mac   = memp.base_mac   + extend_mac;
  735.  
  736.  
  737.   link_stack_length_in_k = stack_len/K;
  738.   link_heap_length_in_k  = mem_cur_heap;
  739.   link_const_length_in_k = mem_cur_const;
  740. }
  741.  
  742. static long get_num_item( dp, item )
  743. DialogPtr dp;
  744. short item;
  745. { short i;
  746.   Rect r;
  747.   Handle h;
  748.   long n;
  749.   Str255 s;
  750.   GetDItem( dp, item, &i, &h, &r );
  751.   GetIText( h, s );
  752.   for (i=s[0]; i>0; i--) if ((s[i] < '0') || (s[i] > '9')) return -1;
  753.   StringToNum( s, &n );
  754.   if (n > 32767) return -1;
  755.   return n;
  756. }
  757.  
  758. static void set_num_item( dp, item, val )
  759. DialogPtr dp;
  760. short item;
  761. long val;
  762. { short i;
  763.   Rect r;
  764.   Handle h;
  765.   long n;
  766.   Str255 s;
  767.   NumToString( val, s );
  768.   GetDItem( dp, item, &i, &h, &r );
  769.   SetIText( h, s );
  770. }
  771.  
  772. static void partition_dialog()
  773. { Str255 s;
  774.   DialogPtr dp;
  775.   short i;
  776.   Handle h;
  777.   Rect r;
  778.  
  779.   long base_heap, extend_heap;
  780.   long base_const, extend_const;
  781.   long base_zzzzz, extend_zzzzz;
  782.   long base_mac, extend_mac;
  783.  
  784.   dp = GetNewDialog( partition_dlogID, 0L, (WindowPtr)-1L );
  785.   if (dp == NULL) return;
  786.  
  787.   SetCursor( &arrow );
  788.  
  789.   set_num_item( dp, 6,  mem_cur_heap );  set_num_item( dp, 7,  mem_min_heap );
  790.   set_num_item( dp, 12, mem_cur_const ); set_num_item( dp, 13, mem_min_const );
  791.   set_num_item( dp, 18, mem_cur_zzzzz ); set_num_item( dp, 19, mem_min_zzzzz );
  792.   set_num_item( dp, 24, mem_cur_mac );   set_num_item( dp, 25, mem_min_mac );
  793.  
  794.   base_heap  = memp.base_heap;  extend_heap  = memp.extend_heap;
  795.   base_const = memp.base_const; extend_const = memp.extend_const;
  796.   base_zzzzz = memp.base_zzzzz; extend_zzzzz = memp.extend_zzzzz;
  797.   base_mac   = memp.base_mac;   extend_mac   = memp.extend_mac;
  798.  
  799.   set_items:
  800.  
  801.   set_num_item( dp, 8,  base_heap );  set_num_item( dp, 9,  extend_heap );
  802.   set_num_item( dp, 14, base_const ); set_num_item( dp, 15, extend_const );
  803.   set_num_item( dp, 20, base_zzzzz ); set_num_item( dp, 21, extend_zzzzz );
  804.   set_num_item( dp, 26, base_mac );   set_num_item( dp, 27, extend_mac );
  805.  
  806.   SelIText( dp, 8, 0, 32767 );
  807.  
  808.   do
  809.   { ModalDialog( 0L, &i );
  810.     switch( i )
  811.     { case 1:
  812.         base_heap    = get_num_item( dp, 8 );
  813.         extend_heap  = get_num_item( dp, 9 );
  814.         base_const   = get_num_item( dp, 14 );
  815.         extend_const = get_num_item( dp, 15 );
  816.         base_zzzzz   = get_num_item( dp, 20 );
  817.         extend_zzzzz = get_num_item( dp, 21 );
  818.         base_mac     = get_num_item( dp, 26 );
  819.         extend_mac   = get_num_item( dp, 27 );
  820.         if ((base_heap  >= mem_min_heap ) && (extend_heap  >= 0) &&
  821.             (base_const >= mem_min_const) && (extend_const >= 0) &&
  822.             (base_zzzzz >= mem_min_zzzzz) && (extend_zzzzz >= 0) &&
  823.             (base_mac   >= mem_min_mac  ) && (extend_mac   >= 0))
  824.         {
  825.           if ((base_heap  != memp.base_heap ) || (extend_heap  != memp.extend_heap ) ||
  826.               (base_const != memp.base_const) || (extend_const != memp.extend_const) ||
  827.               (base_zzzzz != memp.base_zzzzz) || (extend_zzzzz != memp.extend_zzzzz) ||
  828.               (base_mac   != memp.base_mac  ) || (extend_mac   != memp.extend_mac  ))
  829.           {
  830.             struct mem_partition **memph;
  831.             memp.base_heap  = base_heap;  memp.extend_heap  = extend_heap;
  832.             memp.base_const = base_const; memp.extend_const = extend_const;
  833.             memp.base_zzzzz = base_zzzzz; memp.extend_zzzzz = extend_zzzzz;
  834.             memp.base_mac   = base_mac;   memp.extend_mac   = extend_mac;
  835.             memph = (struct mem_partition **)GetResource( 'gamP', 128 );
  836.             if ((memph != NULL) && (SizeResource(memph) == sizeof(struct mem_partition)))
  837.             {
  838.               **memph = memp;
  839.               ChangedResource(memph);
  840.               WriteResource(memph);
  841.               ReleaseResource(memph);
  842.             }
  843.           }
  844.           break;
  845.         }
  846.         else
  847.         {
  848.           SysBeep( 10 );
  849.           i = 0;
  850.           break;
  851.         }
  852.       case 2:
  853.         break;
  854.       case 3: ;
  855.         base_heap  = mem_min_heap;  extend_heap  = DEFAULT_EXTEND_HEAP;
  856.         base_const = mem_min_const; extend_const = DEFAULT_EXTEND_CONST;
  857.         base_zzzzz = mem_min_zzzzz; extend_zzzzz = DEFAULT_EXTEND_ZZZZZ;
  858.         base_mac   = mem_min_mac;   extend_mac   = DEFAULT_EXTEND_MAC;
  859.         goto set_items;
  860.     }
  861.   } while( i != 1 && i != 2 );
  862.   DisposDialog( dp );
  863. }
  864.  
  865. /*----------------------------------------------------------------------*/
  866.  
  867. static short handle_menu( result, id )
  868. long result;
  869. short id;
  870. { short theItem, theMenu, m, w;
  871.   MenuHandle mh;
  872.   WindowPeek wPtr;
  873.   Str255 name;
  874.  
  875.   theItem = LoWord( result );
  876.   theMenu = HiWord( result );
  877.   if (theMenu == 0) return 1;
  878.   mh = GetMHandle( theMenu );
  879.   for (m=appleM; m<=windowsM; m++) if (menus[m] == mh) break;
  880.   switch (m)
  881.   { case appleM:
  882.       if (theItem == 1)
  883.       { DialogPtr dp;
  884.         short i;
  885.         ParamText1( "\p" );
  886.         dp = GetNewDialog( about_dlogID, 0L, (WindowPtr)-1L );
  887.         if (dp != NULL)
  888.         { ModalDialog( 0L, &i );
  889.           DisposDialog( dp );
  890.         }
  891.       }
  892.       else if (theItem == 2)
  893.         online_help();
  894.       else
  895.       { GetItem(menus[appleM], theItem, &name);
  896.         OpenDeskAcc( &name );
  897.       }
  898.       break;
  899.     case fileM: 
  900.       switch (theItem)
  901.       { case newCommand:
  902.         { short w = wind_open( "Untitled", TRUE, TRUE, FALSE );
  903.           if (w < 0)
  904.             wind_err();
  905.           else
  906.             wind_table[w].is_file = 1;
  907.           break;
  908.         }
  909.         case openCommand:
  910.         { short i;
  911.           for (i=0; i<MAX_NB_WINDOWS; i++) if (!wind_table[i].in_use) break;
  912.           if (i == MAX_NB_WINDOWS)
  913.             wind_err();
  914.           else
  915.           { char path[FILENAME_LEN];
  916.             if (get_file( "\p", 1, "TEXT", path, FILENAME_LEN ))
  917.               edit( path, 0L, 0L );
  918.           }
  919.           break;
  920.         }
  921.         case closeCommand:
  922.           if (id >= 0)
  923.             handle_close( id );
  924.           else
  925.             help_hide_if_frontmost();
  926.           break;
  927.         case saveCommand:
  928.           if (id >= 0)
  929.             if (wind_table[id].is_file && (wind_table[id].filename[0] != '\0'))
  930.             { write_file( id );
  931.               break;
  932.             }
  933.         case saveasCommand:
  934.           if (id >= 0)
  935.           { char path[FILENAME_LEN];
  936.             Str255 flnm;
  937.             pathstr_to_filename( wind_table[id].filename, flnm );
  938.             if (put_file( "\pSave as:", flnm, path, FILENAME_LEN ))
  939.               save_as( id, path );
  940.           }
  941.           break;
  942.         case revertCommand:
  943.           if (id >= 0)
  944.             read_file( id, 0L, 0L );
  945.           break;
  946.         /* 25Sep92  e  added print menu items */
  947.         case pgsetupCommand:
  948.           if (id >= 0)
  949.             handle_pgsetup( id );
  950.           break;
  951.         case printCommand:
  952.           if (id >= 0)
  953.             handle_print( id );
  954.           break;
  955.         case quitCommand:
  956.           wind_quit();
  957.           if (gDoQuit) os_quit(); /* 29Dec92  e  */
  958.           break;
  959.       }
  960.       break;
  961.     /* 10Jan93  e  -- separated out Search menu */
  962.     case editM: 
  963.       if (id < 0)
  964.         SystemEdit(theItem-1);
  965.       else
  966.       { TeHANDLE hTE = wind_table[id].hTE;
  967.         switch (theItem)
  968.         { case undoCommand:
  969.             eTeUndo( hTE );
  970.             eMaybeSmudgeWindow( id, hTE );
  971.             break;
  972.           case cutCommand:
  973.             check_TECut( hTE );
  974.             eMaybeSmudgeWindow( id, hTE );
  975.             break;
  976.           case copyCommand:
  977.             check_TECopy( hTE );
  978.             break;
  979.           case pasteCommand:
  980.             check_TEPaste( hTE, wind_table[id].bold_input );
  981.             eMaybeSmudgeWindow( id, hTE );
  982.             break;
  983.           case clearCommand:
  984.             eTeDelete( hTE );
  985.             eMaybeSmudgeWindow( id, hTE );
  986.             break;
  987.           case selAllCommand:
  988.             eTeSetSelect( hTE, 0, eTeTextLength( hTE ));
  989.             break;
  990.           case balanceCommand:
  991.             balance_next( id );
  992.             break;
  993.           case smKeyBdCommand:
  994.               smKeyBdP ^= 1;
  995.               doKeyBdMode();
  996.               break;
  997.           case stylesCommand:
  998.             eStyleDlg( hTE );
  999.               break;
  1000.           case partitionCommand:
  1001.             partition_dialog();
  1002.               break;
  1003. #if (eTe_SHOW_POSN > 0)
  1004.           case showPosnCommand:    /* 10Jan93  e  */
  1005.               showPosnP ^= 1;
  1006.             CheckItem( menus[editM], showPosnCommand, showPosnP );
  1007.             for (w=0; w<MAX_NB_WINDOWS; w++)
  1008.                 if (wind_table[w].in_use) really_inval_msgrect( w );
  1009.               break;
  1010. #endif
  1011.           default: ;
  1012.         }
  1013.         eTeShowCaret( hTE );
  1014.       }
  1015.       break;
  1016.     case findM: 
  1017.       if (id >= 0)
  1018.       { TeHANDLE hTE = wind_table[id].hTE;
  1019.         switch (theItem)
  1020.         { case findCommand:
  1021.             find_dialog( id );
  1022.             break;
  1023.           case againCommand:
  1024.             find_next( id );
  1025.             break;
  1026.           case replaceCommand:
  1027.             replace_next( id );
  1028.             eMaybeSmudgeWindow( id, hTE );
  1029.             break;
  1030.           case fEnterCommand:
  1031.           { long sel_sta, sel_end, sel_len = 0;
  1032.             if( (**hTE).selActive ) {
  1033.               sel_sta = eTeChPosToOffset( hTE, (**hTE).selStart );
  1034.               sel_end = eTeChPosToOffset( hTE, (**hTE).selEnd );
  1035.               sel_len = sel_end - sel_sta;
  1036.             }
  1037.             if (sel_len > 0)
  1038.             { if( sel_len > 255 ) sel_len = 255;
  1039.               buf_to_p( (unsigned short)sel_len, *((**hTE).hText) + sel_sta, find_string );
  1040.             }
  1041.             else
  1042.               SysBeep( 1 );
  1043.             break;
  1044.           }
  1045.           case replaceAllCommand:    /* 08Jan93  e  */
  1046.             replace_all( id );
  1047.             eMaybeSmudgeWindow( id, hTE );
  1048.             break;
  1049.         }
  1050.         eTeShowCaret( hTE );
  1051.       }
  1052.       break;
  1053.     case commandM: 
  1054.       switch (theItem)
  1055.       { case helpCommand:
  1056.           put_input( interaction_id, " ,?", 3, 1, 1, 1 );
  1057.           break;
  1058.         case interruptCommand:
  1059.           interrupt();
  1060.           HiliteMenu(0);
  1061.           return 0;
  1062.         case returnCommand:
  1063.           put_input( interaction_id, " ,r", 3, 1, 1, 1 );
  1064.           break;
  1065.         case abortCommand:
  1066.           put_input( ((id < 0) || (wind_table[id].is_file))?interaction_id:id, "\004", 1, 0, 1, 0 );
  1067.           break;
  1068.         case toplevelCommand:
  1069.           put_input( interaction_id, " ,t", 3, 1, 1, 1 );
  1070.           break;
  1071.         case nextCommand:
  1072.           put_input( interaction_id, " ,+", 3, 1, 1, 1 );
  1073.           break;
  1074.         case previousCommand:
  1075.           put_input( interaction_id, " ,-", 3, 1, 1, 1 );
  1076.           break;
  1077.         case backtraceCommand:
  1078.           put_input( interaction_id, " ,b", 3, 1, 1, 1 );
  1079.           break;
  1080.         case procedureCommand:
  1081.           put_input( interaction_id, " ,i", 3, 1, 1, 1 );
  1082.           break;
  1083.         case expressionCommand:
  1084.           put_input( interaction_id, " ,y", 3, 1, 1, 1 );
  1085.           break;
  1086.         case localsCommand:
  1087.           put_input( interaction_id, " ,l", 3, 1, 1, 1 );
  1088.           break;
  1089.         default:
  1090.           break;
  1091.         }
  1092.       break;
  1093.     case windowsM:
  1094.       switch(theItem)
  1095.       { case 1:
  1096.           select_and_show( wind_table[interaction_id].wptr );
  1097.           break;
  1098.         case 2: /* blank line */
  1099.           break;
  1100.         default:
  1101.           theItem -= fustItem;
  1102.           if(theItem < qWindItems)
  1103.             SelectWindow( wind_table[itemtowindid[theItem]].wptr );
  1104.           break;
  1105.       }
  1106.       break;
  1107.     default:
  1108.       { char s[10], *p2 = s+10, *p1 = p2;
  1109.         do { *--p1 = (result%10)+'0'; result /= 10; } while (result > 0);
  1110.         put_input( interaction_id, " (mac#menuselection ", 21, 0, 1, 0 );
  1111.         put_input( interaction_id, p1, p2-p1, 0, 0, 0 );
  1112.         put_input( interaction_id, ")", 1, 1, 0, 1 );
  1113.         return 1;
  1114.       }
  1115.    }
  1116.   HiliteMenu(0);
  1117.   return 1;
  1118. }
  1119.  
  1120. static short do_tasks()
  1121. { short w;
  1122.   register short i;
  1123.   short men;
  1124.   EventRecord event;
  1125.   Rect r;
  1126.   RgnHandle rgn;
  1127. #if (eTe_SHOW_POSN > 0)
  1128.   long ticks = TickCount();
  1129. #endif
  1130.  
  1131.   for (i=0; i<MAX_NB_WINDOWS; i++)
  1132.     if (wind_table[i].in_use)
  1133.     { if (wind_table[i].out_len > 0)
  1134.       { HLock( wind_table[i].out_buf );    /* 10Jan93  e  */
  1135.         check_TEWrite( *wind_table[i].out_buf, (long)wind_table[i].out_len, wind_table[i].hTE, 0 );
  1136.         HUnlock( wind_table[i].out_buf );
  1137.         wind_table[i].out_len = 0;
  1138.       }
  1139. #if (eTe_SHOW_POSN > 0)
  1140.       /* 10Jan93  e -- added display of caret position */
  1141.       if ( wind_table[i].needs_inval_ticks != 0
  1142.            && ( wind_table[i].needs_inval_ticks + 15 ) < ticks )
  1143.       { really_inval_msgrect( i );
  1144.         wind_table[i].needs_inval_ticks = 0;
  1145.       }
  1146. #endif
  1147.     }
  1148.  
  1149.   w = wptr_to_id( FrontWindow() );
  1150.   if ( (!gInBackground) && (w >= 0) )
  1151.   { Point pt;
  1152.     Cursor *curs;
  1153.     OSEventAvail(0L, &event); /* This returns a NULL event with the global mouse location */
  1154.     if( gCursRgnOK && PtInRgn( event.where, gCursorRgn ) )
  1155.     { /* punt... SetCursor( current_cursor ); */
  1156.     }
  1157.     else
  1158.     { SetPort( (GrafPtr)wind_table[w].wptr );
  1159.       r = (**wind_table[w].hTE).viewRect;
  1160.       LocalToGlobal((Point *)&(r.top));      /* topLeft  */
  1161.       LocalToGlobal((Point *)&(r.bottom));   /* botRight */
  1162.       if (PtInRect( event.where, &r ))
  1163.       { curs = &ibeam_cursor;
  1164.         RectRgn(gCursorRgn, &r);
  1165.       }
  1166.       else
  1167.       { curs = &arrow;
  1168.         SetRectRgn(gCursorRgn, -32768, -32768, 32766, 32766);
  1169.         rgn = NewRgn();
  1170.         RectRgn(rgn, &r);
  1171.         DiffRgn(gCursorRgn, rgn, gCursorRgn);
  1172.         DisposeRgn(rgn);
  1173.       }
  1174.       if (!gCursRgnOK || current_cursor != curs)
  1175.       { current_cursor = curs;
  1176.         SetCursor( current_cursor );
  1177.       }
  1178.       gCursRgnOK = true;
  1179.     }
  1180.     eTeIdle( wind_table[w].hTE );
  1181.     men = (wind_table[w].is_file && (wind_table[w].filename[0] != '\0')) ? 1 : 0;
  1182.   }
  1183.   else
  1184.   { SetRectRgn(gCursorRgn, -32768, -32768, 32766, 32766);
  1185.     gCursRgnOK = false;
  1186.     SetCursor(&qd.arrow);    /*  13Oct92  e  */
  1187.     men = 2;
  1188.   }
  1189.  
  1190.   if ( (!gInBackground) && (men != current_menus) )
  1191.   { current_menus = men;
  1192.     switch (men)
  1193.     { case 0:
  1194.       case 1:
  1195.         /*
  1196.         EnableItem( menus[fileM], newCommand );
  1197.         EnableItem( menus[fileM], openCommand );
  1198.         EnableItem( menus[fileM], closeCommand );
  1199.         */
  1200.         EnableItem( menus[fileM], saveCommand );
  1201.         EnableItem( menus[fileM], saveasCommand );
  1202.         if (men == 0)
  1203.           DisableItem( menus[fileM], revertCommand );
  1204.         else
  1205.           EnableItem( menus[fileM], revertCommand );
  1206.         /*
  1207.         EnableItem( menus[fileM], quitCommand );
  1208.         */
  1209.         EnableItem( menus[fileM], pgsetupCommand );
  1210.         EnableItem( menus[fileM], printCommand );
  1211.         EnableItem( menus[editM], selAllCommand );
  1212.         EnableItem( menus[editM], balanceCommand );
  1213.         EnableItem( menus[editM], smKeyBdCommand );
  1214.         EnableItem( menus[editM], stylesCommand );
  1215.         EnableItem( menus[editM], partitionCommand );
  1216.         EnableItem( menus[editM], showPosnCommand );
  1217.         /*
  1218.         EnableItem( menus[findM], findCommand );
  1219.         EnableItem( menus[findM], againCommand );
  1220.         EnableItem( menus[findM], replaceCommand );
  1221.         EnableItem( menus[findM], replaceAllCommand );
  1222.         EnableItem( menus[findM], fEnterCommand ); */
  1223.         EnableItem( menus[findM], 0 );
  1224.         /*
  1225.         EnableItem( menus[commandM], 0 );
  1226.         */
  1227.         DrawMenuBar();
  1228.         break;
  1229.       case 2:
  1230.         /*
  1231.         DisableItem( menus[fileM], newCommand );
  1232.         DisableItem( menus[fileM], openCommand );
  1233.         DisableItem( menus[fileM], closeCommand );
  1234.         */
  1235.         DisableItem( menus[fileM], saveCommand );
  1236.         DisableItem( menus[fileM], saveasCommand );
  1237.         DisableItem( menus[fileM], revertCommand );
  1238.         /*
  1239.         DisableItem( menus[fileM], quitCommand );
  1240.         */
  1241.         DisableItem( menus[fileM], pgsetupCommand );
  1242.         DisableItem( menus[fileM], printCommand );
  1243.         DisableItem( menus[editM], selAllCommand );
  1244.         DisableItem( menus[editM], balanceCommand );
  1245.         DisableItem( menus[editM], smKeyBdCommand );
  1246.         DisableItem( menus[editM], stylesCommand );
  1247.         DisableItem( menus[editM], partitionCommand );
  1248.         DisableItem( menus[editM], showPosnCommand );
  1249.         /*
  1250.         DisableItem( menus[findM], findCommand );
  1251.         DisableItem( menus[findM], againCommand );
  1252.         DisableItem( menus[findM], replaceCommand );
  1253.         DisableItem( menus[findM], replaceAllCommand );
  1254.         DisableItem( menus[findM], fEnterCommand ); */
  1255.         DisableItem( menus[findM], 0 );
  1256.         /*
  1257.         DisableItem( menus[commandM], 0 );
  1258.         */
  1259.         DrawMenuBar();
  1260.         break;
  1261.     }
  1262.   }
  1263.  
  1264.   if ( (!gInBackground) && (w>=0) )
  1265.   { register EvQElPtr q;
  1266.     for (q = (EvQElPtr)EventQueue.qHead; q != NULL; q = (EvQElPtr)q->qLink)
  1267.       if ((q->evtQWhat == keyDown) && ((char)q->evtQMessage == '.') &&
  1268.           (q->evtQModifiers & cmdKey))
  1269.       { while (GetNextEvent(keyDownMask+keyUpMask+autoKeyMask,&event) &&
  1270.                !((event.what == keyDown) && ((event.message & charCodeMask) == '.') &&
  1271.                  ((event.modifiers & cmdKey) != 0) )) ;
  1272.         interrupt();
  1273.         return 0;
  1274.       }
  1275.   }
  1276.   return 1;
  1277. }
  1278.  
  1279. /* from MacDTS */
  1280. #define kDITop                    0x0050        /* kTopLeft - for positioning the Disk */
  1281. #define kDILeft                    0x0070        /*   Initialization dialogs. */
  1282.  
  1283. void handle_activate( WindowPtr wptr, Boolean activep )
  1284. { GrafPtr port;
  1285.   Rect r;
  1286.   short w = wptr_to_id( wptr );
  1287.   if( w >= 0 )
  1288.   { port = wind_table[w].wptr;
  1289.     r = port->portRect;
  1290.     r.left = r.right - (SBarWidth+1);
  1291.     SetPort( port );
  1292.     InvalRect( &r );
  1293.     r = port->portRect;
  1294.     r.top = r.bottom - (SBarWidth+1);
  1295.     InvalRect( &r );
  1296.     if ( activep )
  1297.     { eTeActivate( wind_table[w].hTE );
  1298.       ShowControl( wind_table[w].vscroll );
  1299.       ShowControl( wind_table[w].hscroll );
  1300.     }
  1301.     else
  1302.     { eTeDeactivate( wind_table[w].hTE );
  1303.       HideControl( wind_table[w].vscroll );
  1304.       HideControl( wind_table[w].hscroll );
  1305.     }
  1306.   }
  1307. }
  1308.  
  1309. static short handle_event( event )
  1310. EventRecord *event;
  1311. { register short i;
  1312.   short w;
  1313.   WindowPtr event_window;
  1314.  
  1315.   if (IsDialogEvent( event ))
  1316.   { DialogPtr dp;
  1317.     short item;
  1318.     DialogSelect( event, &dp, &item );
  1319.     return 1;
  1320.   }
  1321.  
  1322.   if (help_event( event )) return 1;
  1323.  
  1324.   w = wptr_to_id( FrontWindow() );
  1325.   { switch (event->what)
  1326.     { case mouseDown:
  1327.         gCursRgnOK = false;
  1328.         switch (FindWindow(event->where,&event_window))
  1329.         { case inDesk: 
  1330.             SysBeep( 10 );
  1331.             break;
  1332.           case inGoAway:
  1333.             if ((w = wptr_to_id( event_window )) >= 0)
  1334.               if (TrackGoAway(event_window,event->where)) handle_close( w );
  1335.             break;
  1336.           case inMenuBar:
  1337.           { TeHANDLE hTE = NULL;
  1338.             if( w >= 0) hTE = wind_table[w].hTE;
  1339.             eTeEditMenuUpdate( hTE, menus[editM] );
  1340.             return handle_menu( MenuSelect(event->where), w );
  1341.           }
  1342.           case inSysWindow:
  1343.             SystemClick(event,event_window);
  1344.             break;
  1345.           case inDrag:
  1346.             if ((w = wptr_to_id( event_window )) >= 0)
  1347.               DragWindow(event_window,event->where,&screenBits.bounds);
  1348.             break;
  1349.           case inGrow:
  1350.             if ((w = wptr_to_id( event_window )) >= 0)
  1351.               grow_window( w, event->where );
  1352.             break;
  1353.           case inContent:
  1354.             if (event_window != FrontWindow())
  1355.               SelectWindow(event_window);
  1356.             else 
  1357.               if ((w = wptr_to_id( event_window )) >= 0)
  1358.                 content( w, event );
  1359.             break;
  1360.           default: ;
  1361.         }
  1362.         gLastMouseDown = *event;
  1363.         break;
  1364.       case mouseUp:
  1365.         gLastMouseUp = *event;
  1366.         break;
  1367.       case keyDown:
  1368.       case autoKey:
  1369.         { char c = event->message & charCodeMask;
  1370.           TeHANDLE hTE = (w>=0)?wind_table[w].hTE:NULL;
  1371.           if ((c == '\r' /*cr*/) && ((event->modifiers & (cmdKey|optionKey)) != 0))
  1372.             event->modifiers = optionKey;
  1373.           else if( smKeyBdP )
  1374.           { /* hokey */
  1375.             if( (event->modifiers & optionKey) != 0 )
  1376.               { if( (event->modifiers & cmdKey) == 0 )
  1377.                   event->modifiers &= ~optionKey;    /* option key gets state of command key */
  1378.                 event->modifiers &= ~cmdKey;        /* turn off command key */
  1379.                 event->modifiers |= controlKey;        /* turn on  control key */
  1380.                 c -= 0x40;    /* its (close to) what control key would have done */
  1381.               }
  1382.           }
  1383.           if ((event->modifiers & cmdKey) != 0)
  1384.           { long res;
  1385.             if (c == '=') c = '+'; else if (c == '/') c = '?';
  1386.             if (hTE != NULL) eTeEditMenuUpdate( hTE, menus[editM] );
  1387.             res = MenuKey( c );
  1388.             if( HiWord( res ) != 0 )
  1389.                 return handle_menu( res, w );
  1390.             if( (hTE != NULL) && (c >= 0) && (c <= 31) )
  1391.             {   check_TEKey( c, hTE, 0, event );
  1392.                 inval_msgrect( w ); /* 10Jan93  e -- added display of caret position */
  1393.             }
  1394.             break;
  1395.           }
  1396.           if (hTE == NULL) break;
  1397.           if( ( event->modifiers & controlKey ) != 0 )
  1398.           { eEditCommand( hTE, c, event->modifiers, wind_table[w].bold_input );
  1399.               eMaybeSmudgeWindow( w, hTE );
  1400.               inval_msgrect( w );
  1401.           }
  1402.           else
  1403.           { if( ( c == 3 /*enter*/ ) || (( c == '\r' /*cr*/ ) && ((event->modifiers & optionKey) != 0 )))
  1404.             { short id = (wind_table[w].is_file) ? interaction_id : w;
  1405.               long sel_sta, sel_end, sel_len, dummy;
  1406.               if( (**hTE).selActive )
  1407.               { sel_sta = eTeChPosToOffset( hTE, (**hTE).selStart );
  1408.                   sel_end = eTeChPosToOffset( hTE, (**hTE).selEnd );
  1409.               }
  1410.               else
  1411.               { sel_end = eTeChPosToOffset( hTE, (**hTE).caretChPos );
  1412.                 if (c == 3 /*enter*/)
  1413.                     eTeGetRun( hTE, &sel_sta, &dummy );
  1414.                 else
  1415.                 { sel_sta = balance( w, 0, 1 );
  1416.                   if (sel_sta < 0) sel_sta = sel_end;
  1417.                 }
  1418.               }
  1419.               sel_len = sel_end - sel_sta;
  1420.               HLock((**hTE).hText);
  1421.               if (sel_len > 0)
  1422.               { eTeSetSelect( hTE, sel_end, sel_end );
  1423.                 put_input( id, *((**hTE).hText) + sel_sta, sel_len, 1, 0, 1 );
  1424.               }
  1425.               else
  1426.                 SysBeep(10);
  1427.               HUnlock((**hTE).hText);
  1428.             }
  1429.             else if (c == 9) /*tab*/
  1430.             { eTabCommand( hTE, event->modifiers, wind_table[w].bold_input );
  1431.               eMaybeSmudgeWindow( w, hTE );
  1432.               inval_msgrect( w ); /* 10Jan93  e -- added display of caret position */
  1433.             }
  1434.             else if( ( c == 127 /* del fwd */ )  || ( (c >= 0) && (c <= 31) ) )
  1435.             { check_TEKey( c, hTE, wind_table[w].bold_input, event );
  1436.               if ((c == '\r') && (**hTE).autoInd)
  1437.                 eTabCommand( hTE, event->modifiers, wind_table[w].bold_input );
  1438.               eMaybeSmudgeWindow( w, hTE );
  1439.               inval_msgrect( w ); /* 10Jan93  e -- added display of caret position */
  1440.             }
  1441.             else
  1442.             { if (!check_TEKey( c, hTE, wind_table[w].bold_input, event ))
  1443.                 if (c == ')')
  1444.                 { long open_paren = balance( w, 0, 0 );
  1445.                   if (open_paren >= 0)
  1446.                   { long now;
  1447.                     long selstart = eTeChPosToOffset( hTE, (**hTE).caretChPos );
  1448.                     eTeSetSelect( hTE, open_paren, open_paren+1 );
  1449.                     eTeShowCaret( hTE );
  1450.                     now = TickCount();
  1451.                     while ((TickCount()-now)<10) ;
  1452.                     while (!EventAvail(everyEvent,event) && ((TickCount()-now)<30)) ;
  1453.                     eTeSetSelect( hTE, selstart, selstart );
  1454.                   }
  1455.                 }
  1456.               eMaybeSmudgeWindow( w, hTE );
  1457.               inval_msgrect( w ); /* 10Jan93  e -- added display of caret position */
  1458.               eTeShowCaret( hTE );
  1459.             }
  1460.           }
  1461.         }
  1462.         break;
  1463.       case activateEvt:
  1464.         gCursRgnOK = false;
  1465.           handle_activate( (WindowPtr)event->message, ((event->modifiers & activeFlag) != 0) );
  1466.         break;
  1467.       case updateEvt: 
  1468.         if ((w = wptr_to_id( (WindowPtr)event->message )) >= 0)
  1469.         { update_window(w);
  1470.         }
  1471.         else
  1472.         { GrafPtr port = (WindowPtr)event->message;
  1473.           SetPort( port );
  1474.           BeginUpdate( port );
  1475.           EndUpdate( port );
  1476.         }
  1477.         break;
  1478.       case osEvt:
  1479.         if( *(char *)(&event->message) == suspendResumeMessage )
  1480.         { gCursRgnOK = false; /* Suspend/resume is also an activate/deactivate. */
  1481.           gInBackground = !(event->message & resumeFlag);
  1482.           if( gInBackground ) eTePutScrap();                  /*  13Aug92  e  */
  1483.           else                  eTeGetScrap();                  /*  13Aug92  e  */
  1484.           handle_activate( FrontWindow(), !gInBackground );
  1485.         }
  1486.         /* punt mouseMovedMessage */
  1487.         break;
  1488.       case diskEvt:
  1489.         gCursRgnOK = false;                     /* It is not a bad idea to at least call */
  1490.         if (HiWord(event->message) != noErr) /* DIBadMount in response to a diskEvt,  */
  1491.         { Point pt;                             /* so that the user can format a floppy. */
  1492.           SetPt( &pt, kDILeft, kDITop );
  1493.           DIBadMount( pt, event->message );
  1494.         }
  1495.         break;
  1496.       /* 29Dec92  e  */
  1497.       case kHighLevelEvent:
  1498.         AEProcessAppleEvent(event);
  1499.         if (gDoQuit) os_quit();
  1500.         break;
  1501.       default: ;
  1502.     }
  1503.   }
  1504.   return 1;
  1505. }
  1506.  
  1507. static long wind_read( id, ptr, n )
  1508. short id;
  1509. char *ptr;
  1510. long n;
  1511. { if (n > 0)
  1512.   { register short len;
  1513.     if ((len = wind_table[id].len - wind_table[id].pos) > 0)
  1514.     { register char *p1 = ptr;
  1515.       register char *p2 = wind_table[id].buf + wind_table[id].pos;
  1516.       register short i = 0;
  1517.       if (p2[i] == '\004') { wind_table[id].pos++; return 0; }
  1518.       if (len > n) len = n;
  1519.       while ((i < len) && (p2[i] != '\004'))
  1520.       { register char c = p2[i++];
  1521.         if (c == '\r') c = '\n';
  1522.         *p1++ = c;
  1523.       }
  1524.       wind_table[id].pos += i;
  1525.       return i;
  1526.     }
  1527.     else
  1528.       return -2;
  1529.   }
  1530.   else
  1531.     return 0;
  1532. }
  1533.  
  1534. static long wind_write( id, ptr, n )
  1535. short id;
  1536. char *ptr;
  1537. long n;
  1538. { register char *p1 = ptr, *p2 = ptr+n;
  1539.   register short len = wind_table[id].out_len;
  1540.   register char *p3; /*  = wind_table[id].out_buf; */
  1541.   /* 10Jan93  e  */
  1542.   if( wind_table[id].out_buf == NULL )
  1543.   { wind_table[id].out_buf = NewHandle( OUT_BUF_LEN );
  1544.     if( wind_table[id].out_buf == NULL )
  1545.     { SysBeep(10);
  1546.       return 0;
  1547.     }
  1548.   }
  1549.   HLock( wind_table[id].out_buf );
  1550.   p3 = (char *)*wind_table[id].out_buf;
  1551.  
  1552.   if (!((WindowPeek)wind_table[id].wptr)->visible)
  1553.     select_and_show( wind_table[id].wptr );
  1554.  
  1555.   while (p1<p2)
  1556.   { register char c = *p1++;
  1557.     if (c == '\n') { p3[len++] = '\r'; goto output; }
  1558.     p3[len++] = c;
  1559.     if (len == OUT_BUF_LEN)
  1560.     { output:
  1561.       if (check_TEWrite( p3, (long)len, wind_table[id].hTE, 0 )) goto werror;
  1562.       wind_table[id].out_len = 0;
  1563.       len = 0;
  1564.     }
  1565.   }
  1566.   wind_table[id].out_len = len;
  1567. werror:
  1568.   HUnlock( wind_table[id].out_buf );
  1569.   return n;
  1570. }
  1571.  
  1572. /*--------------------------------------------------------------------------*/
  1573.  
  1574. /* new stuff  29Dec92  e  */
  1575.  
  1576. /* Used to check for any unread required parameters. Returns true if we
  1577. ** missed at least one. */
  1578.  
  1579. static Boolean    MissedAnyParameters(AppleEvent *message)
  1580. {
  1581.     OSErr        err;
  1582.     DescType    ignoredActualType;
  1583.     AEKeyword    missedKeyword;
  1584.     Size        ignoredActualSize;
  1585.     EventRecord    event;
  1586.  
  1587.     err = AEGetAttributePtr(    /* SEE IF PARAMETERS ARE ALL USED UP.          */
  1588.         message,                /* AppleEvent to check.                          */
  1589.         keyMissedKeywordAttr,    /* Look for unread parameters.                  */
  1590.         typeWildCard,            /* So we can see what type we missed, if any. */
  1591.         &ignoredActualType,        /* What it would have been if not coerced.      */
  1592.         (Ptr)&missedKeyword,    /* Data area.  (Keyword not handled.)          */
  1593.         sizeof(missedKeyword),    /* Size of data area.                          */
  1594.         &ignoredActualSize        /* Actual data size.                          */
  1595.     );
  1596.  
  1597. /* No error means that we found some unused parameters. */
  1598.  
  1599.     if (err == noErr) {
  1600.         event.message = *(long *) &ignoredActualType;
  1601.         event.where = *(Point *) &missedKeyword;
  1602.         err = errAEEventNotHandled;
  1603.     }
  1604.  
  1605. /* errAEDescNotFound means that there are no more parameters.  If we get
  1606. ** an error code other than that, flag it. */
  1607.  
  1608.     return(err != errAEDescNotFound);
  1609. }
  1610.  
  1611. static OSErr    OpenDocEventHandler(AppleEvent *message, AppleEvent *reply, short mode)
  1612. {
  1613.     OSErr        err;
  1614.     OSErr        err2;
  1615.     AEDesc        theDesc;
  1616.     FSSpec        theFSS;
  1617.     short        loop;
  1618.     long        numFilesToOpen;
  1619.     AEKeyword    ignoredKeyWord;
  1620.     DescType    ignoredType;
  1621.     Size        ignoredSize;
  1622.     char path[512];
  1623.     short w;
  1624.     Str255 flnm;
  1625.     FInfo theFInfo;
  1626.  
  1627.     theDesc.dataHandle = nil;
  1628.         /* Make sure disposing of the descriptors is okay in all cases.
  1629.         ** This will not be necessary after 7.0b3, since the calls that
  1630.         ** attempt to create the descriptors will nil automatically
  1631.         ** upon failure. */
  1632.  
  1633.     if ( err = AEGetParamDesc( message, keyDirectObject, typeAEList, &theDesc ) )
  1634.         return(err);
  1635.  
  1636.     if ( ! MissedAnyParameters( message ) ) {
  1637.  
  1638. /* Got all the parameters we need.  Now, go through the direct object,
  1639. ** see what type it is, and parse it up. */
  1640.  
  1641.         err = AECountItems(&theDesc, &numFilesToOpen);
  1642.         if (!err)
  1643.         {    /* We have numFilesToOpen that need opening, as either a window
  1644.             ** or to be printed.  Go to it... */
  1645.  
  1646.             for (loop = 1; ((loop <= numFilesToOpen) && (!err)); ++loop)
  1647.             {    err = AEGetNthPtr(        /* GET NEXT IN THE LIST...         */
  1648.                     &theDesc,            /* List of file names.             */
  1649.                     loop,                /* Item # in the list.             */
  1650.                     typeFSS,            /* Item is of type FSSpec.         */
  1651.                     &ignoredKeyWord,    /* Returned keyword -- we know.  */
  1652.                     &ignoredType,        /* Returned type -- we know.     */
  1653.                     (Ptr)&theFSS,        /* Where to put the FSSpec info. */
  1654.                     sizeof(theFSS),        /* Size of the FSSpec info.         */
  1655.                     &ignoredSize        /* Actual size -- we know.         */
  1656.                 );
  1657.                 if (err) break;
  1658.  
  1659.                 FSpGetFInfo( &theFSS, &theFInfo );
  1660.                 if ( theFInfo.fdType != 'TEXT' )
  1661.                 { SysBeep( 3 );
  1662.                   continue;
  1663.                 }
  1664.  
  1665.                 gPrintPage = mode;
  1666.                     /* Open the window off-screen if we are printing.
  1667.                     ** We use the gPrintPage global to flag this.  Normally, the
  1668.                     ** gPrintPage global is to tell ImageDocument if we are imaging
  1669.                     ** to the window or to paper.  We don't need it for this yet,
  1670.                     ** as we can't image the document until it is opened.  DoNewWindow()
  1671.                     ** uses gPrintPage as a flag to open the window off-screen, but
  1672.                     ** visible, so that PrintMonitor can use the title of the window
  1673.                     ** as the document name that is being printed. */
  1674.                 
  1675.                 if ( getfullpath( theFSS.vRefNum, theFSS.parID, theFSS.name, path, 511, 1 ) )
  1676.                 {    
  1677.                     w = edit( path, 0L, 0L );
  1678.  
  1679.                     if ( gPrintPage && w >= 0 )
  1680.                     {    pathstr_to_filename( wind_table[w].filename, flnm );
  1681.                         err  = eTePrint( wind_table[w].hTE, (mode == 2), (loop == 1), flnm );
  1682.                         mode = 1;    /* No interaction mode (mode == 2) only valid
  1683.                                     ** for the first printed document. */
  1684.                         wind_close( w );
  1685.                     }
  1686.                 }
  1687.                 else err = errAEEventNotHandled;     /* file pathname too long */
  1688.             }
  1689.             if (gPrintPage)
  1690.             {    eTePrint( nil, false, false, flnm ); /* cleanup */
  1691.                 gPrintPage = 0;                     /* back to normal */
  1692.             }
  1693.         }
  1694.     }
  1695.     err2 = AEDisposeDesc(&theDesc);
  1696.     return(err ? err : err2);
  1697. }
  1698.  
  1699. static Boolean install_aehandler( AEEventClass cl, AEEventID id, ProcPtr p )
  1700. { OSErr    err;
  1701.   err = AEInstallEventHandler( cl, id, p, 0L, false );
  1702.   if (err)
  1703.   { io_err(err);
  1704.     return false;
  1705.   }
  1706.   return true;
  1707. }
  1708.  
  1709. static pascal OSErr    DoAEOpenApplication( AppleEvent *message, AppleEvent *reply, long refcon )
  1710. {
  1711.     return(noErr);
  1712. }
  1713.  
  1714. static pascal OSErr    DoAEOpenDocuments( AppleEvent *message, AppleEvent *reply, long refcon )
  1715. {
  1716.     gCursRgnOK = false;
  1717.     return( OpenDocEventHandler( message, reply, 0 ) ); /* 0 means regular open document */
  1718. }
  1719.  
  1720. #define kTimeOutInTicks (60 * 30)    /* 30 second timeout. */
  1721.  
  1722. static pascal OSErr    DoAEPrintDocuments(AppleEvent *message, AppleEvent *reply, long refcon)
  1723. {
  1724.     short                openMode;
  1725.     ProcessSerialNumber    cpsn, fpsn;
  1726.     Boolean                procsSame;
  1727.  
  1728.     gCursRgnOK = false;
  1729.     openMode = 1;
  1730.     if (!AEInteractWithUser(kTimeOutInTicks, nil, nil))
  1731.         ++openMode;
  1732.  
  1733.     GetCurrentProcess(&cpsn);        /* We may have been moved to the front. */
  1734.     GetFrontProcess(&fpsn);
  1735.     SameProcess(&cpsn, &fpsn, &procsSame);
  1736.     gInBackground = !procsSame;
  1737.  
  1738.     return( OpenDocEventHandler( message, reply, openMode ) );
  1739.         /* openMode is either 1 or 2, depending if user interaction is okay. */
  1740. }
  1741.  
  1742. static pascal OSErr    DoAEQuitApplication( AppleEvent *message, AppleEvent *reply, long refcon )
  1743. {
  1744.     gCursRgnOK = false;
  1745.     wind_quit();
  1746.     return( gDoQuit ? noErr : errAEEventNotHandled );
  1747. }
  1748.  
  1749. /* 1Feb93  e  --  DoScript added */
  1750.  
  1751. static OSErr DoScriptAsFile( FSSpec *theFSS )
  1752. {
  1753.     OSErr err = noErr;
  1754.     short len;
  1755.     char  path[512];
  1756.     
  1757.     if( len = getfullpath( theFSS->vRefNum, theFSS->parID, theFSS->name, path, 511, 1 ) )
  1758.     {
  1759.         put_input( interaction_id, " (load \"", 6, 0, 0, 1 );
  1760.         put_input( interaction_id, path, len, 0, 0, 0 );
  1761.         put_input( interaction_id, "\")", 2, 1, 0, 0 );
  1762.     }
  1763.     else err = errAEEventNotHandled;
  1764.     return err;
  1765. }
  1766.  
  1767. static pascal OSErr DoAEDoScript( AppleEvent *theAEEvent, AppleEvent *theAEReply, long *theRefCon)
  1768. {
  1769.     OSErr        theErr;
  1770.     DescType    typeCode;
  1771.     Size        sizeOfParam, actualSize;
  1772.     char        ourScriptText[256];
  1773.     FSSpec        ourScriptFSpec;
  1774.  
  1775.     /* Get the script to run */ 
  1776.  
  1777.     theErr = AESizeOfParam( theAEEvent, keyDirectObject, &typeCode, &sizeOfParam);
  1778.     if (theErr != noErr)
  1779.     {    /*
  1780.             If we fail here just return the error. We don't need to do any clean up since 
  1781.             we've allocated nothing on the heap yet.  The Apple Event Manager automatically 
  1782.             adds the error number to the reply as keyErrorNumber for non zero handler returns.
  1783.         */
  1784.         return theErr;
  1785.     }
  1786.     else if ((typeCode == typeChar) || (typeCode == typeStyledText) || (typeCode == typeIntlText))
  1787.     {
  1788.         theErr = AEGetParamPtr( theAEEvent, keyDirectObject, typeChar, &typeCode,
  1789.                                  (Ptr)&ourScriptText, sizeof(ourScriptText), &actualSize);
  1790.         if (theErr == noErr)
  1791.             if ( MissedAnyParameters( theAEEvent ) )
  1792.                 theErr = errAEEventNotHandled;
  1793.             else put_input( interaction_id, ourScriptText, actualSize, 1, 0, 1 );
  1794.     }
  1795.     else if (typeCode == typeAlias)
  1796.     {
  1797.         theErr = AEGetParamPtr( theAEEvent, keyDirectObject, typeFSS, &typeCode,
  1798.                                 (Ptr)&ourScriptFSpec, sizeof(ourScriptFSpec), &actualSize);
  1799.         if ( theErr == noErr )
  1800.             if ( MissedAnyParameters( theAEEvent ) )
  1801.                 theErr = errAEEventNotHandled;
  1802.             else theErr = DoScriptAsFile( &ourScriptFSpec );
  1803.     }
  1804.     else theErr = errAEEventNotHandled;
  1805.     return theErr;
  1806. }
  1807.  
  1808.  
  1809. static void init_ae()
  1810. {
  1811.     long    result;
  1812.  
  1813.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &result) ? false : result != 0);
  1814.  
  1815.     if (gHasAppleEvents)
  1816.          install_aehandler( kCoreEventClass, kAEOpenApplication, (ProcPtr)DoAEOpenApplication )
  1817.       && install_aehandler( kCoreEventClass, kAEOpenDocuments, (ProcPtr)DoAEOpenDocuments )
  1818.       && install_aehandler( kCoreEventClass, kAEPrintDocuments, (ProcPtr)DoAEPrintDocuments )
  1819.       && install_aehandler( kCoreEventClass, kAEQuitApplication, (ProcPtr)DoAEQuitApplication )
  1820.       && install_aehandler( kAEMiscStandards, kAEDoScript, (ProcPtr)DoAEDoScript );
  1821. }
  1822.  
  1823. /*---------------------------------------------------------------------------*/
  1824.  
  1825. #define TICKS_PER_SEC 60
  1826.  
  1827. short *link_ofiles[] =
  1828. { (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1829.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1830.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1831.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1832.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1833.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1834.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1835.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1836.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1837.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1838.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1839.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1840.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1841.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1842.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      ",
  1843.   (short *)"      ", (short *)"      ", (short *)"      ", (short *)"      "
  1844. };
  1845.  
  1846. static long sizeof_ofiles[] =
  1847. { 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
  1848.   0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
  1849.   0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
  1850.   0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
  1851. };
  1852.  
  1853. long *link_sizeof_ofiles[] =
  1854. { &sizeof_ofiles[ 0], &sizeof_ofiles[ 1], &sizeof_ofiles[ 2], &sizeof_ofiles[ 3],
  1855.   &sizeof_ofiles[ 4], &sizeof_ofiles[ 5], &sizeof_ofiles[ 6], &sizeof_ofiles[ 7],
  1856.   &sizeof_ofiles[ 8], &sizeof_ofiles[ 9], &sizeof_ofiles[10], &sizeof_ofiles[11],
  1857.   &sizeof_ofiles[12], &sizeof_ofiles[13], &sizeof_ofiles[14], &sizeof_ofiles[15],
  1858.   &sizeof_ofiles[16], &sizeof_ofiles[17], &sizeof_ofiles[18], &sizeof_ofiles[19],
  1859.   &sizeof_ofiles[20], &sizeof_ofiles[21], &sizeof_ofiles[22], &sizeof_ofiles[23],
  1860.   &sizeof_ofiles[24], &sizeof_ofiles[25], &sizeof_ofiles[26], &sizeof_ofiles[27],
  1861.   &sizeof_ofiles[28], &sizeof_ofiles[29], &sizeof_ofiles[30], &sizeof_ofiles[31],
  1862.   &sizeof_ofiles[32], &sizeof_ofiles[33], &sizeof_ofiles[34], &sizeof_ofiles[35],
  1863.   &sizeof_ofiles[36], &sizeof_ofiles[37], &sizeof_ofiles[38], &sizeof_ofiles[39],
  1864.   &sizeof_ofiles[40], &sizeof_ofiles[41], &sizeof_ofiles[42], &sizeof_ofiles[43],
  1865.   &sizeof_ofiles[44], &sizeof_ofiles[45], &sizeof_ofiles[46], &sizeof_ofiles[47],
  1866.   &sizeof_ofiles[48], &sizeof_ofiles[49], &sizeof_ofiles[50], &sizeof_ofiles[51],
  1867.   &sizeof_ofiles[52], &sizeof_ofiles[53], &sizeof_ofiles[54], &sizeof_ofiles[55],
  1868.   &sizeof_ofiles[56], &sizeof_ofiles[57], &sizeof_ofiles[58], &sizeof_ofiles[59],
  1869.   &sizeof_ofiles[60], &sizeof_ofiles[61], &sizeof_ofiles[62], &sizeof_ofiles[63]
  1870. };
  1871.  
  1872. long link_nb_ofiles;
  1873.  
  1874. long prog_len;
  1875.  
  1876.  
  1877. long start_real_time;
  1878.  
  1879.  
  1880. long os_nb_processors()
  1881. { return 1;
  1882. }
  1883.  
  1884.  
  1885. long os_fork_on_processors( n )
  1886. long n;
  1887. { return 0;
  1888. }
  1889.  
  1890.  
  1891. void os_shared_malloc8( len, processor, cont )
  1892. long len;
  1893. long processor;
  1894. void (*cont)();
  1895. { long appl_limit = (((long)&appl_limit) - len - ((long)MAC_STACK_LEN_IN_K)*K) & -4L;
  1896.   long lim = ((long)ApplZone) + ((long)MAC_HEAP_LEN_IN_K)*K;
  1897.   if (lim < ((long)HeapEnd)+1024) lim = ((long)HeapEnd)+1024;
  1898.   if (appl_limit < lim)
  1899.     cont( (long)NULL );
  1900.   else
  1901.   { SetApplLimit( (void *)appl_limit );
  1902.     asm
  1903.     { move.l cont,a0
  1904.       move.l sp,d0
  1905.       move.l d0,d1
  1906.       sub.l  len,d1
  1907.       and.w  #-8,d1
  1908.       move.l d1,sp
  1909.       move.l d0,-(sp)
  1910.       move.l d1,-(sp)
  1911.       jsr    (a0)
  1912.       move.l 4(sp),sp
  1913.     }
  1914.   }
  1915. }
  1916.  
  1917.  
  1918. void os_shared_copy_malloc8( len_share, len_copy, processor, cont )
  1919. long len_share, len_copy;
  1920. long processor;
  1921. void (*cont)();
  1922. { long aligned_len_share = ceiling8( len_share );
  1923.   long len = aligned_len_share + len_copy;
  1924.   long offs = aligned_len_share - len_share;
  1925.   long appl_limit = (((long)&appl_limit) - len - ((long)MAC_STACK_LEN_IN_K)*K) & -4L;
  1926.   long lim = ((long)ApplZone) + ((long)MAC_HEAP_LEN_IN_K)*K;
  1927.   if (lim < ((long)HeapEnd)+1024) lim = ((long)HeapEnd)+1024;
  1928.   if (appl_limit < lim)
  1929.     cont( (long)NULL );
  1930.   else
  1931.   { SetApplLimit( (void *)appl_limit );
  1932.     asm
  1933.     { move.l offs,d2
  1934.       move.l cont,a0
  1935.       move.l sp,d0
  1936.       move.l d0,d1
  1937.       sub.l  len,d1
  1938.       and.w  #-8,d1
  1939.       move.l d1,sp
  1940.       move.l d0,-(sp)
  1941.       add.l  d2,d1
  1942.       move.l d1,-(sp)
  1943.       jsr    (a0)
  1944.       move.l 4(sp),sp
  1945.     }
  1946.   }
  1947. }
  1948.  
  1949.  
  1950. void os_block_copy( src, dst, len )
  1951. char *src, *dst;
  1952. long len;
  1953. { register char *p1 = src, *p2 = dst;
  1954.   register long i = len;
  1955.   while (i > 0) { *(p2++) = *(p1++); i--; }
  1956. }
  1957.  
  1958.  
  1959. void os_flush_caches()
  1960. { if (gHasHWPriv)
  1961.   asm
  1962.   { moveq #1,d0
  1963.     dc.w _HWPriv
  1964.   }
  1965.   else if (os_M68020)
  1966.   {
  1967. #define INSTR_CACHE_LENGTH_IN_K 64
  1968. #define DATA_CACHE_LENGTH_IN_K  8
  1969.  
  1970.     short *start = (short *)pstate->heap_old;
  1971.     short *p = start;
  1972.     long i;
  1973.  
  1974.     for (i=((long)INSTR_CACHE_LENGTH_IN_K)*K/2-1; i>0; i--) *p++ = NOP_OP;
  1975.     *p++ = RTS_OP;
  1976.     for (i=((long)DATA_CACHE_LENGTH_IN_K)*K/2; i>0; i--) *p++ = 0;
  1977.  
  1978.     ((void (*)())start)();
  1979.   }
  1980. }
  1981.  
  1982.  
  1983. void os_flush_writes()
  1984. { if (gHasHWPriv)
  1985.   asm
  1986.   { moveq #1,d0
  1987.     dc.w _HWPriv
  1988.   }
  1989. }
  1990.  
  1991.  
  1992. long os_clock()
  1993. { return TickCount() - start_real_time;
  1994. }
  1995.  
  1996.  
  1997. long os_real_time_clock()
  1998. { return TickCount() - start_real_time;
  1999. }
  2000.  
  2001.  
  2002. long os_clock_to_msec( ticks )
  2003. long ticks;
  2004. { return ticks * 1000 / TICKS_PER_SEC;
  2005. }
  2006.  
  2007.  
  2008. void os_cpu_times( buf )
  2009. long *buf;
  2010. { buf[0] = (TickCount() - start_real_time) * 1000 / TICKS_PER_SEC;
  2011.   buf[1] = 0;
  2012. }
  2013.  
  2014.  
  2015. void os_profil( buff, bufsiz, offset, shift )
  2016. short *buff;
  2017. long bufsiz, offset;
  2018. long shift;
  2019. {
  2020. }
  2021.  
  2022.  
  2023. long os_ticks_to_msec( ticks )
  2024. long ticks;
  2025. { return ticks * 1000 / TICKS_PER_SEC;
  2026. }
  2027.  
  2028.  
  2029. static void fatal_signal( pc, sp, kind )
  2030. long pc, sp;
  2031. char *kind;
  2032. { os_warn( "Fatal signal %s, terminating...\n", (long)kind );
  2033.   os_quit();
  2034. }
  2035.  
  2036.  
  2037. void os_install_trap_handlers( intr_proc, timer_proc, io_proc, fatal_proc )
  2038. void (*intr_proc)();
  2039. void (*timer_proc)();
  2040. void (*io_proc)();
  2041. void (*fatal_proc)();
  2042. { intr_action = intr_proc;
  2043.   timer_action = timer_proc;
  2044.   io_action = io_proc;
  2045.   if (fatal_proc != (void (*)())0)
  2046.     fatal_action = fatal_proc;
  2047.   else
  2048.     fatal_action = fatal_signal;
  2049.  
  2050.   if (loading_dp != NULL)
  2051.   { DisposDialog( loading_dp ); loading_dp = NULL; }
  2052.  
  2053.   MaxApplZone();
  2054.  
  2055.   start_intr_task();
  2056. }
  2057.  
  2058.  
  2059. long os_get_next_event( event )
  2060. EventRecord *event;
  2061. { long result = 0;
  2062.   GrafPtr save;
  2063.   GetPort( &save );
  2064.   if (do_tasks())
  2065.   { if (gHasWNE)
  2066.       { result = (long)( gInBackground ? gWaitTicksBG    /* 22Jul92  e   -- added gMaxSleep */
  2067.                                          : (long )( (gWaitTicksFG > gMaxSleep) ? gMaxSleep
  2068.                                                                                 : gWaitTicksFG) );
  2069.       result = WaitNextEvent( everyEvent, event, result, gCursorRgn );
  2070.     }
  2071.     else
  2072.     { SystemTask();
  2073.       result = GetNextEvent( everyEvent, event );
  2074.     }
  2075.   }
  2076.   SetPort( save );
  2077.   return result;
  2078. }
  2079.  
  2080. long os_handle_event( event )
  2081. EventRecord *event;
  2082. { long result;
  2083.   GrafPtr save;
  2084.   GetPort( &save );
  2085.   result = handle_event( event );
  2086.   SetPort( save );
  2087.   return result;
  2088. }
  2089.  
  2090.  
  2091. char *os_expand_filename( str )
  2092. char *str;
  2093. { return str;
  2094. }
  2095.  
  2096.  
  2097. struct {
  2098.   short type; /* -1 = not in use, 0 = text file, 1 = bin file, 2 = resource, 3 = window */
  2099.   long pos;
  2100.   short refnum;
  2101.   } os_file[MAX_NB_OPEN_FILES];
  2102.  
  2103.  
  2104. short appl_res_file;
  2105. Handle appl_res_map;
  2106.  
  2107. static short read_resource( type, id, n, ptr )  /* Ugly, but works... */
  2108. ResType type;
  2109. short id;
  2110. long n;
  2111. char *ptr;
  2112. { short i, j;
  2113.   long count;
  2114.   struct type_list_rec { short id, name_offs; long data_offs, reserved; };
  2115.   struct map_entry_rec { ResType type; short nb_minus_1; short offs; };
  2116.   struct map_rec
  2117.   { char pad[24]; short type_list_offs, name_list_offs, nb_minus_1;
  2118.     struct map_entry_rec entry[1];
  2119.   };
  2120.   struct map_rec *map = (struct map_rec *)*appl_res_map;
  2121.  
  2122.   i = map->nb_minus_1;
  2123.   while (i >= 0)
  2124.   { if (map->entry[i].type == type)
  2125.     { struct type_list_rec *item = (struct type_list_rec *)(((char *)map)+map->type_list_offs+map->entry[i].offs);
  2126.       j = map->entry[i].nb_minus_1;
  2127.       while (j >= 0)
  2128.       { if (item[j].id == id)
  2129.         { if (SetFPos( appl_res_file, 1, item[j].data_offs + 260L ) != noErr) return 0;
  2130.           count = n;
  2131.           if (FSRead( appl_res_file, &count, ptr ) != noErr) return 0;
  2132.           return 1;
  2133.         }
  2134.         j--;
  2135.       }
  2136.     }
  2137.     i--;
  2138.   }
  2139.   return 0;
  2140. }
  2141.  
  2142.  
  2143. static long file_open( name, for_output )
  2144. char *name;
  2145. long for_output;
  2146. { long i;
  2147.   for (i=0; i<(long)MAX_NB_OPEN_FILES; i++) if (os_file[i].type < 0) break;
  2148.   if (i == (long)MAX_NB_OPEN_FILES) return -1;
  2149.  
  2150.   if (name[0] == 1) /* opening 'gamO' resource */
  2151.   { Handle h;
  2152.     short j = 1, n = 0;
  2153.     EventRecord event;
  2154.     while (os_get_next_event( &event )) os_handle_event( &event );
  2155.     if (for_output) return -1;
  2156.     while ((name[j]>='0') && (name[j]<='9')) n = n*10 + (name[j++] - '0');
  2157.     SetResLoad( FALSE );
  2158.     h = GetResource( 'gamO', n );
  2159.     SetResLoad( TRUE );
  2160.     if (h == NULL) return -1;
  2161.     ReleaseResource( h );
  2162.     os_file[i].type   = 2;
  2163.     os_file[i].refnum = n;
  2164.     os_file[i].pos    = 0;
  2165.   }
  2166.   else if (name[0] == 2) /* opening window */
  2167.   { GrafPtr save;
  2168.     GetPort( &save );
  2169.     os_file[i].refnum = wind_open( name+1, TRUE, TRUE, TRUE );
  2170.     if (os_file[i].refnum < 0) i = -1; else os_file[i].type = 3;
  2171.     SetPort( save );
  2172.   }
  2173.   else
  2174.   { short io;
  2175.     short bin, len;
  2176.     Str255 pname;
  2177.     c_to_p( name, pname );
  2178.     len = (unsigned char)pname[0];
  2179.     bin = ((len >= 2) && (pname[len-1] == '.') && (pname[len] == 'O'));
  2180.     os_file[i].refnum = open_file( pname, (short)for_output, !bin, &io );
  2181.     if (os_file[i].refnum == -1) return -1;
  2182.     os_file[i].type = bin;
  2183.   }
  2184.  
  2185.   return i;
  2186. }
  2187.  
  2188. OS_FILE os_file_open_input( name )
  2189. char *name;
  2190. { return (OS_FILE)file_open( name, 0L );
  2191. }
  2192.  
  2193.  
  2194. OS_FILE os_file_open_output( name )
  2195. char *name;
  2196. { return (OS_FILE)file_open( name, 1L );
  2197. }
  2198.  
  2199.  
  2200. OS_FILE os_file_open_input_output( name )
  2201. char *name;
  2202. { return (OS_FILE)file_open( name, 1L );
  2203. }
  2204.  
  2205.  
  2206. long os_file_length( f )
  2207. OS_FILE f;
  2208. { long len;
  2209.   switch (os_file[f].type)
  2210.   { case 0:
  2211.     case 1:
  2212.     { if (GetEOF( os_file[f].refnum, &len ) != noErr) return -1;
  2213.       break;
  2214.     }
  2215.     case 2:
  2216.     { Handle h;
  2217.       SetResLoad( FALSE );
  2218.       h = GetResource( 'gamO', os_file[f].refnum );
  2219.       SetResLoad( TRUE );
  2220.       if (h == NULL) return -1;
  2221.       len = SizeResource( h );
  2222.       ReleaseResource( h );
  2223.       break;
  2224.     }
  2225.     case 3:
  2226.       return -1;
  2227.     default:
  2228.       return -1;
  2229.   }
  2230.   return len;
  2231. }
  2232.  
  2233.  
  2234. long os_file_read_ready( f )
  2235. OS_FILE f;
  2236. { if (os_file[f].type == 3)
  2237.   { short id = os_file[f].refnum;
  2238.     return ((wind_table[id].len - wind_table[id].pos) > 0);
  2239.   }
  2240.   else
  2241.     return 1;
  2242. }
  2243.  
  2244.  
  2245. long os_file_write_ready( f )
  2246. OS_FILE f;
  2247. { return 1;
  2248. }
  2249.  
  2250.  
  2251. void os_file_block_read( f )
  2252. OS_FILE f;
  2253. {
  2254. }
  2255.  
  2256.  
  2257. void os_file_block_write( f )
  2258. OS_FILE f;
  2259. {
  2260. }
  2261.  
  2262.  
  2263. long os_file_read( f, ptr, n )
  2264. OS_FILE f;
  2265. char *ptr;
  2266. long n;
  2267. { switch (os_file[f].type)
  2268.   { case 0:
  2269.     case 1:
  2270.     { long count = n;
  2271.       FSRead( os_file[f].refnum, &count, ptr );
  2272.       if (os_file[f].type == 0)
  2273.       { register char *p = ptr;
  2274.         register long len = count;
  2275.         while (len-- > 0) { if (*p == '\r') *p = '\n'; p++; }
  2276.       }
  2277.       return count;
  2278.     }
  2279.     case 2:
  2280.       if (read_resource( 'gamO', os_file[f].refnum, n, ptr ))
  2281.         return n;
  2282.       else
  2283.         return -2;
  2284.     case 3:
  2285.     { long result;
  2286.       GrafPtr save;
  2287.       GetPort( &save );
  2288.       result = wind_read( os_file[f].refnum, ptr, n );
  2289.       SetPort( save );
  2290.       return result;
  2291.     }
  2292.     default:
  2293.       return -2;
  2294.   }
  2295. }
  2296.  
  2297.  
  2298. long os_file_write( f, ptr, n )
  2299. OS_FILE f;
  2300. char *ptr;
  2301. long n;
  2302. { switch (os_file[f].type)
  2303.   { case 0:
  2304.     { char buffer[1024+8];
  2305.       register char *p1 = ptr, *p2 = ptr+n;
  2306.       register short len = 0;
  2307.  
  2308.       while (p1<p2)
  2309.       { register char c = *p1++;
  2310.         if (c == '\n') buffer[len++] = '\r'; else buffer[len++] = c;
  2311.         if (len == 1024)
  2312.         { long count = len;
  2313.           FSWrite( os_file[f].refnum, &count, buffer );
  2314.           if (count != len) return (p1-ptr)-len+count;
  2315.           len = 0;
  2316.         }
  2317.       }
  2318.       if (len > 0)
  2319.       { long count = len;
  2320.         FSWrite( os_file[f].refnum, &count, buffer );
  2321.         if (count != len) return (p1-ptr)-len+count;
  2322.       }
  2323.       return (p1-ptr);
  2324.     }
  2325.     case 1:
  2326.     { long count = n;
  2327.       FSWrite( os_file[f].refnum, &count, ptr );
  2328.       return count;
  2329.     }
  2330.     case 2:
  2331.       return -2;
  2332.     case 3:
  2333.     { long result;
  2334.       GrafPtr save;
  2335.       GetPort( &save );
  2336.       result = wind_write( os_file[f].refnum, ptr, n );
  2337.       SetPort( save );
  2338.       return result;
  2339.     }
  2340.     default:
  2341.       return -2;
  2342.   }
  2343. }
  2344.  
  2345.  
  2346. long os_file_close( f )
  2347. OS_FILE f;
  2348. { switch (os_file[f].type)
  2349.   { case 0:
  2350.     case 1:
  2351.     { short io;
  2352.       os_file[f].type = -1;
  2353.       if (close_file( os_file[f].refnum, &io )) return -1;
  2354.       return 0;
  2355.     }
  2356.     case 2:
  2357.     { os_file[f].type = -1;
  2358.       return 0;
  2359.     }
  2360.     case 3:
  2361.     { long result = 0;
  2362.       GrafPtr save;
  2363.       GetPort( &save );
  2364.       if (os_file[f].refnum < 0)
  2365.         result = -1;
  2366.       else
  2367.       { if (os_file[f].refnum != interaction_id) os_file[f].type = -1;
  2368.         wind_close( os_file[f].refnum );
  2369.       }
  2370.       SetPort( save );
  2371.       return result;
  2372.     }
  2373.     default:
  2374.       return -1;
  2375.   }
  2376. }
  2377.  
  2378.  
  2379. extern void os_set_timer_interval( interval )
  2380. long interval;
  2381. { intr_task_interval = (interval * TICKS_PER_SEC + 999) / 1000;
  2382. }
  2383.  
  2384.  
  2385. void os_quit()
  2386. { short i;
  2387.   long ticks;
  2388.   stop_intr_task();
  2389.   for (i=MAX_NB_OPEN_FILES-1; i>0; i--) os_file_close( (OS_FILE)i );
  2390.   if (abnormal_exit)
  2391.   { for (i=0; i<3; i++) { SysBeep(3); Delay( 3, &ticks ); }
  2392.     Delay( 60, &ticks );
  2393.   }
  2394.   wind_end();
  2395.   help_end();
  2396.   ExitToShell();
  2397. }
  2398.  
  2399.  
  2400. static void os_notify_gc_begin_internal()
  2401. { SetCursor( &gc_cursor );
  2402. }
  2403.  
  2404.  
  2405. static void os_notify_gc_end_internal()
  2406. { SetCursor( current_cursor );
  2407. }
  2408.  
  2409.  
  2410. extern void main_gambit();
  2411.  
  2412.  
  2413. #define MAX_ARGS 2
  2414.  
  2415. static short main_internal( argc, argv, envp )
  2416. short argc;
  2417. char *argv[], *envp[];
  2418. { char new_args[256];
  2419.   short new_argc;
  2420.   char *new_argv[MAX_ARGS+1];
  2421.   char *new_envp[] = { "MAC", NULL };
  2422.   SysEnvRec sysenv;
  2423.   Handle h;
  2424.   short i;
  2425.   long ofiles_len;
  2426.   DialogPtr dp;
  2427.   THz heap = ApplicZone();
  2428.  
  2429.   appl_res_file = CurResFile();
  2430.   appl_res_map = TopMapHndl;
  2431.  
  2432.   MoreMasters();
  2433.   MoreMasters();
  2434.   MoreMasters();
  2435.   MoreMasters();
  2436.   CouldAlert( ok_alertID );
  2437.   SetGrowZone( mem_full_err );
  2438.  
  2439.   InitGraf( &thePort );
  2440.   InitFonts();
  2441.   FlushEvents( everyEvent, 0 );
  2442.   InitWindows();
  2443.   InitMenus();
  2444.   TEInit();
  2445.   eTeInit();
  2446.   InitDialogs( 0L );
  2447.   InitCursor();
  2448.  
  2449.   GetVol( new_args, ¤t_volume );
  2450.   if (!getfullpathfromcurrentvolume( CurApName, new_args, 256, 0 ))
  2451.     p_to_c( CurApName, new_args );
  2452.  
  2453.   help_begin( "\pOnline Help", CurApName );
  2454.  
  2455.   wind_begin();
  2456.  
  2457.   new_argc = 0;
  2458.   new_argv[new_argc++] = new_args;
  2459.   new_argv[new_argc] = NULL;
  2460.  
  2461.   for (i=0; i<MAX_NB_OPEN_FILES; i++) os_file[i].type = -1;
  2462.   os_file[0].type   = 3;
  2463.   os_file[0].refnum = wind_open( "Interaction", FALSE, FALSE, TRUE );
  2464.   interaction_id = os_file[0].refnum;
  2465.   if (interaction_id < 0) os_quit();
  2466.   delWindMenuItem( interaction_id );
  2467.  
  2468.   i = 128;
  2469.   ofiles_len = 0;
  2470.   link_nb_ofiles = 0;
  2471.   again:
  2472.   SetResLoad( FALSE ); h = GetResource( 'gamO', i ); SetResLoad( TRUE );
  2473.   if (h != NULL)
  2474.   { short j = 0, d = 10000, n = i;
  2475.     ((char *)link_ofiles[link_nb_ofiles])[j++] = 1;
  2476.     while (d>0)
  2477.     { ((char *)link_ofiles[link_nb_ofiles])[j++] = n/d + '0'; n = n%d; d = d/10; }
  2478.     ((char *)link_ofiles[link_nb_ofiles])[j++] = '\0';
  2479.     ofiles_len += SizeResource(h);
  2480.     ReleaseResource( h );
  2481.     link_nb_ofiles++;
  2482.     i++;
  2483.     goto again;
  2484.   }
  2485.  
  2486.   { short msg, count;
  2487.     CountAppFiles( &msg, &count );
  2488.     if (msg == appOpen)
  2489.     { for (i=1; i<=count; i++)
  2490.       { char path[FILENAME_LEN];
  2491.         AppFile file_info;
  2492.         GetAppFiles( i, &file_info );
  2493.         if ((file_info.fType == 'TEXT') &&
  2494.             getfullpathfromwd( (long)file_info.vRefNum, (StringPtr)file_info.fName, path, FILENAME_LEN, 1 ))
  2495.         { if (edit( path, 0L, 0L ) < 0) break;
  2496.           current_volume = file_info.vRefNum;
  2497.           ClrAppFiles( i );
  2498.         }
  2499.         else if (file_info.fType == 'gamO')
  2500.         { char *ofile;
  2501.           long count;
  2502.           short refnum;
  2503.           short io;
  2504.           io = FSOpen( file_info.fName, file_info.vRefNum, &refnum );
  2505.           if (io != noErr) { io_err( io ); return 0; }
  2506.           io = GetEOF( refnum, &prog_len );
  2507.           if (io != noErr) { FSClose( refnum ); io_err( io ); return 0; }
  2508.           ofile = NewPtr( prog_len );
  2509.           if (ofile == NULL) return 0;
  2510.           count = prog_len;
  2511.           io = FSRead( refnum, &count, ofile );
  2512.           if ((io != noErr) || (count != prog_len)) { FSClose( refnum ); io_err( io ); return 0; }
  2513.           FSClose( refnum );
  2514.           link_ofiles[link_nb_ofiles-1] = (short *)ofile;
  2515.           link_sizeof_ofiles[link_nb_ofiles-1] = &prog_len;
  2516.           ofiles_len += prog_len;
  2517.           current_volume = file_info.vRefNum;
  2518.           ClrAppFiles( i );
  2519.           break;
  2520.         }
  2521.       }
  2522.     }
  2523.   }
  2524.  
  2525.   SysEnvirons( curSysEnvVers, &sysenv );
  2526.   os_M68020 = (sysenv.processor >= env68020);
  2527.   os_M68881 = sysenv.hasFPU;
  2528.   os_stdin  = 0;
  2529.   os_stdout = 0;
  2530.   os_stderr = 0;
  2531.  
  2532.   start_real_time = TickCount();
  2533.  
  2534.   SetCursor( current_cursor );
  2535.  
  2536.   ParamText1( "\p" );
  2537.   loading_dp = GetNewDialog( loading_dlogID, 0L, (WindowPtr)-1L );
  2538.   if (loading_dp != NULL) DrawDialog( loading_dp );
  2539.  
  2540.   partition_init( ofiles_len );
  2541.  
  2542.   main_gambit( new_argc, new_argv, new_envp );
  2543.  
  2544.   os_quit();
  2545.  
  2546.   return 0;
  2547. }
  2548.  
  2549. /* 6Jul92  e */
  2550. #ifdef THINK_C
  2551. #include "os.c"
  2552. #endif
  2553.  
  2554. /*--------------------------------------------------------------------------*/
  2555.